From 7496349ae36721da2155f3759ffafba8c6c74d79 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 2 Oct 2026 04:15:04 +0900 Subject: [PATCH 1/5] test(evidence): lock exact sensitive access receipt bounds --- CHANGELOG.md | 1 + .../tests/sensitive_access_evidence.rs | 32 +++++++++++++++++++ docs/TEST_STRATEGY.md | 2 ++ 3 files changed, 35 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f747adeae..27770bbd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Refreshed the product-gap queue to 126 open pull requests (54 ready, 72 draft) after #190, #188, #185, #192, #182, #184, #115, #181, #116, #117, #118, #183, #114, #127, #112, #109, #186, #110, #108, #111, #174, and #113 were merged into their immediate stacked prerequisites. PRs #147, #146, #145, #144, #143, #142, #141, #139, #136, #132, #129, and #128 moved to ready after exact-head checks and thread review; these are queue-consolidation results, not protected-main shipment. ### Added +- Added regression tests for the exact 128-byte sensitive-access authority identifier and 64-field receipt bounds; production validation behavior is unchanged. - Corrected the 2026-08-26 product-gap snapshot with current #229 presentation-identity evidence, stacked-only #205 integration evidence, current base/head pairs, the 126-PR queue count, explicit root-versus-child merge ordering, and the active GitHub counted-approval gate. - Refreshed the product and technical gap baseline onto the 2026-08-26 live inventory: 126 open pull requests (54 ready, 72 draft), protected-main promotion of #168/#194/#196/#216/#151, a verified maintenance-loop record (supersession closure of #153, conflict reconciliations on #37/#149/#152/#173/#175, issue #212 option-(b) authorization on #43, Strix vuln-0001 homoglyph remediation on #124), provider-rerun outcome evidence, an organization review-pipeline congestion record, and refreshed merge-order queue guidance. Documentation evidence contracts were aligned to the same snapshot so the baseline, its dated markers, and the pinned exact-head rows cannot silently diverge. diff --git a/crates/originweave-evidence/tests/sensitive_access_evidence.rs b/crates/originweave-evidence/tests/sensitive_access_evidence.rs index 28d6bf348..8be9f4b2b 100644 --- a/crates/originweave-evidence/tests/sensitive_access_evidence.rs +++ b/crates/originweave-evidence/tests/sensitive_access_evidence.rs @@ -147,6 +147,38 @@ fn authority_identifiers_and_field_sets_are_bounded_and_unambiguous() -> TestRes Ok(()) } +#[test] +fn exact_maximum_authority_identifiers_are_accepted() -> TestResult { + let mut input = valid_input()?; + input.request_id = "a".repeat(128); + input.decision_id = "a".repeat(128); + input.tenant_id = "a".repeat(128); + input.actor_id = "a".repeat(128); + input.task_id = "a".repeat(128); + input.purpose_id = "a".repeat(128); + input.policy_version = "a".repeat(128); + input.approval_reference = Some("a".repeat(128)); + input.field_ids = vec!["a".repeat(128)]; + assert!( + SensitiveAccessEvidence::try_from(input).is_ok(), + "all authority identifiers accept the documented 128-byte maximum" + ); + Ok(()) +} + +#[test] +fn exact_maximum_field_set_is_accepted() -> TestResult { + let mut input = valid_input()?; + input.field_ids = (0..MAX_SENSITIVE_FIELD_COUNT) + .map(|index| format!("field:{index}")) + .collect(); + assert!( + SensitiveAccessEvidence::try_from(input).is_ok(), + "64 distinct field identifiers are the documented accepted maximum" + ); + Ok(()) +} + #[test] fn disclosure_and_retention_times_fail_closed_when_semantics_are_impossible() -> TestResult { let mut zero_decision = valid_input()?; diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index ba3c31624..7376e9fb5 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -212,6 +212,8 @@ A representative sensitive flow must prove the approved value is usable where th Test wrong tenant/task/field/purpose/origin/audience, expired/revoked handle, max-use/replay, concurrent-use race, break-glass lifecycle and provider-region mismatch. +Sensitive-access evidence regressions accept the documented exact 128-byte authority-identifier limit and 64 distinct protected-field identifiers. Keep the existing oversized, empty, malformed, and duplicate rejection cases; these receipts contain authority metadata, not protected values or disclosure authority. + ## 8. Resource and performance tests ### 8.1 Deterministic governor From 08d6a0adc43179f6331b3021b729cb5fa22d1e48 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 2 Oct 2026 04:46:29 +0900 Subject: [PATCH 2/5] test(evidence): pin documented field count independently --- CHANGELOG.md | 2 +- crates/originweave-evidence/tests/sensitive_access_evidence.rs | 1 + docs/TEST_STRATEGY.md | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 27770bbd6..461b96c17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Refreshed the product-gap queue to 126 open pull requests (54 ready, 72 draft) after #190, #188, #185, #192, #182, #184, #115, #181, #116, #117, #118, #183, #114, #127, #112, #109, #186, #110, #108, #111, #174, and #113 were merged into their immediate stacked prerequisites. PRs #147, #146, #145, #144, #143, #142, #141, #139, #136, #132, #129, and #128 moved to ready after exact-head checks and thread review; these are queue-consolidation results, not protected-main shipment. ### Added -- Added regression tests for the exact 128-byte sensitive-access authority identifier and 64-field receipt bounds; production validation behavior is unchanged. +- Added regression tests for the exact 128-byte sensitive-access authority identifier and 64-field receipt bounds, including an independent literal assertion that detects field-count constant drift; production validation behavior is unchanged. - Corrected the 2026-08-26 product-gap snapshot with current #229 presentation-identity evidence, stacked-only #205 integration evidence, current base/head pairs, the 126-PR queue count, explicit root-versus-child merge ordering, and the active GitHub counted-approval gate. - Refreshed the product and technical gap baseline onto the 2026-08-26 live inventory: 126 open pull requests (54 ready, 72 draft), protected-main promotion of #168/#194/#196/#216/#151, a verified maintenance-loop record (supersession closure of #153, conflict reconciliations on #37/#149/#152/#173/#175, issue #212 option-(b) authorization on #43, Strix vuln-0001 homoglyph remediation on #124), provider-rerun outcome evidence, an organization review-pipeline congestion record, and refreshed merge-order queue guidance. Documentation evidence contracts were aligned to the same snapshot so the baseline, its dated markers, and the pinned exact-head rows cannot silently diverge. diff --git a/crates/originweave-evidence/tests/sensitive_access_evidence.rs b/crates/originweave-evidence/tests/sensitive_access_evidence.rs index 8be9f4b2b..d48308049 100644 --- a/crates/originweave-evidence/tests/sensitive_access_evidence.rs +++ b/crates/originweave-evidence/tests/sensitive_access_evidence.rs @@ -168,6 +168,7 @@ fn exact_maximum_authority_identifiers_are_accepted() -> TestResult { #[test] fn exact_maximum_field_set_is_accepted() -> TestResult { + assert_eq!(MAX_SENSITIVE_FIELD_COUNT, 64); let mut input = valid_input()?; input.field_ids = (0..MAX_SENSITIVE_FIELD_COUNT) .map(|index| format!("field:{index}")) diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index 7376e9fb5..79113d1f0 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -212,7 +212,7 @@ A representative sensitive flow must prove the approved value is usable where th Test wrong tenant/task/field/purpose/origin/audience, expired/revoked handle, max-use/replay, concurrent-use race, break-glass lifecycle and provider-region mismatch. -Sensitive-access evidence regressions accept the documented exact 128-byte authority-identifier limit and 64 distinct protected-field identifiers. Keep the existing oversized, empty, malformed, and duplicate rejection cases; these receipts contain authority metadata, not protected values or disclosure authority. +Sensitive-access evidence regressions accept the documented exact 128-byte authority-identifier limit and 64 distinct protected-field identifiers. Assert the field-count constant independently against the documented literal 64 so a changed production limit cannot silently resize the accepted fixture. Keep the existing oversized, empty, malformed, and duplicate rejection cases; these receipts contain authority metadata, not protected values or disclosure authority. ## 8. Resource and performance tests From 65ac1132d91e6561fec7277298eb671a61bb5a88 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Fri, 2 Oct 2026 11:28:11 +0900 Subject: [PATCH 3/5] test(evidence): lock exact query count and value redaction --- CHANGELOG.md | 1 + .../tests/security_review.rs | 29 +++++++++++++++++++ docs/TEST_STRATEGY.md | 2 ++ 3 files changed, 32 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 461b96c17..a71463a79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to OriginWeave are documented in this file. The format follo ### Added - Added regression tests for the exact 128-byte sensitive-access authority identifier and 64-field receipt bounds, including an independent literal assertion that detects field-count constant drift; production validation behavior is unchanged. +- Added an exact 128-query-field network-evidence regression that independently fixes the documented count, checks every retained name/value-redaction pair, and rejects a 129th field; production capture behavior is unchanged. - Corrected the 2026-08-26 product-gap snapshot with current #229 presentation-identity evidence, stacked-only #205 integration evidence, current base/head pairs, the 126-PR queue count, explicit root-versus-child merge ordering, and the active GitHub counted-approval gate. - Refreshed the product and technical gap baseline onto the 2026-08-26 live inventory: 126 open pull requests (54 ready, 72 draft), protected-main promotion of #168/#194/#196/#216/#151, a verified maintenance-loop record (supersession closure of #153, conflict reconciliations on #37/#149/#152/#173/#175, issue #212 option-(b) authorization on #43, Strix vuln-0001 homoglyph remediation on #124), provider-rerun outcome evidence, an organization review-pipeline congestion record, and refreshed merge-order queue guidance. Documentation evidence contracts were aligned to the same snapshot so the baseline, its dated markers, and the pinned exact-head rows cannot silently diverge. diff --git a/crates/originweave-evidence/tests/security_review.rs b/crates/originweave-evidence/tests/security_review.rs index 5755b2461..bfe4af688 100644 --- a/crates/originweave-evidence/tests/security_review.rs +++ b/crates/originweave-evidence/tests/security_review.rs @@ -124,6 +124,35 @@ fn capture_enforces_path_count_and_value_boundaries() { ); } +#[test] +fn exact_query_field_limit_preserves_names_and_redacts_values() { + assert_eq!(MAX_QUERY_FIELD_COUNT, 128); + let query = (0..128) + .map(|index| { + ( + format!("field-{index}"), + format!("synthetic-private-{index}"), + ) + }) + .collect(); + let evidence = NetworkEvidence::capture(HttpMethod::Get, origin(), "/", BTreeMap::new(), query) + .expect("exactly 128 query fields are accepted"); + assert_eq!(evidence.query().len(), 128); + for index in 0..128 { + assert_eq!( + evidence.query().get(&format!("field-{index}")), + Some(&"[REDACTED]".to_owned()), + ); + } + let oversized = (0..129) + .map(|index| (format!("field-{index}"), "synthetic-private".to_owned())) + .collect(); + assert_eq!( + NetworkEvidence::capture(HttpMethod::Get, origin(), "/", BTreeMap::new(), oversized), + Err(EvidenceError::LimitExceeded), + ); +} + #[test] fn capture_rejects_invalid_or_oversized_metadata_names() { for invalid_name in [ diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index 79113d1f0..e9067c7d0 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -212,6 +212,8 @@ A representative sensitive flow must prove the approved value is usable where th Test wrong tenant/task/field/purpose/origin/audience, expired/revoked handle, max-use/replay, concurrent-use race, break-glass lifecycle and provider-region mismatch. +Network evidence regressions accept exactly 128 query fields, retain every admitted field name with its value redacted, and reject a 129th field. Assert the query-count constant against the independent literal 128 so constant drift cannot silently resize the accepted fixture. These records do not retain query values or grant network authority. + Sensitive-access evidence regressions accept the documented exact 128-byte authority-identifier limit and 64 distinct protected-field identifiers. Assert the field-count constant independently against the documented literal 64 so a changed production limit cannot silently resize the accepted fixture. Keep the existing oversized, empty, malformed, and duplicate rejection cases; these receipts contain authority metadata, not protected values or disclosure authority. ## 8. Resource and performance tests From 18d2dbc7c5a81a83e8b7f5941e0dff8b435b5edf Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 4 Oct 2026 12:25:00 +0900 Subject: [PATCH 4/5] test(evidence): preserve exact-bound receipt metadata --- CHANGELOG.md | 1 + .../tests/sensitive_access_evidence.rs | 25 +++++++++++++------ docs/TEST_STRATEGY.md | 2 ++ 3 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a71463a79..e31680d14 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to OriginWeave are documented in this file. The format follo ### Added - Added regression tests for the exact 128-byte sensitive-access authority identifier and 64-field receipt bounds, including an independent literal assertion that detects field-count constant drift; production validation behavior is unchanged. +- Strengthened exact-bound sensitive-access receipts to compare all eight retained authority identifiers, the 128-byte field identifier and all 64 ordered field identifiers. Ten isolated truncation or omission mutations demonstrate regression sensitivity; production evidence validation and disclosure authority are unchanged. - Added an exact 128-query-field network-evidence regression that independently fixes the documented count, checks every retained name/value-redaction pair, and rejects a 129th field; production capture behavior is unchanged. - Corrected the 2026-08-26 product-gap snapshot with current #229 presentation-identity evidence, stacked-only #205 integration evidence, current base/head pairs, the 126-PR queue count, explicit root-versus-child merge ordering, and the active GitHub counted-approval gate. - Refreshed the product and technical gap baseline onto the 2026-08-26 live inventory: 126 open pull requests (54 ready, 72 draft), protected-main promotion of #168/#194/#196/#216/#151, a verified maintenance-loop record (supersession closure of #153, conflict reconciliations on #37/#149/#152/#173/#175, issue #212 option-(b) authorization on #43, Strix vuln-0001 homoglyph remediation on #124), provider-rerun outcome evidence, an organization review-pipeline congestion record, and refreshed merge-order queue guidance. Documentation evidence contracts were aligned to the same snapshot so the baseline, its dated markers, and the pinned exact-head rows cannot silently diverge. diff --git a/crates/originweave-evidence/tests/sensitive_access_evidence.rs b/crates/originweave-evidence/tests/sensitive_access_evidence.rs index d48308049..8e9707a0e 100644 --- a/crates/originweave-evidence/tests/sensitive_access_evidence.rs +++ b/crates/originweave-evidence/tests/sensitive_access_evidence.rs @@ -159,10 +159,20 @@ fn exact_maximum_authority_identifiers_are_accepted() -> TestResult { input.policy_version = "a".repeat(128); input.approval_reference = Some("a".repeat(128)); input.field_ids = vec!["a".repeat(128)]; - assert!( - SensitiveAccessEvidence::try_from(input).is_ok(), - "all authority identifiers accept the documented 128-byte maximum" + let evidence = validated(input)?; + assert_eq!(evidence.request_id(), "a".repeat(128)); + assert_eq!(evidence.decision_id(), "a".repeat(128)); + assert_eq!(evidence.tenant_id(), "a".repeat(128)); + assert_eq!(evidence.actor_id(), "a".repeat(128)); + assert_eq!(evidence.task_id(), "a".repeat(128)); + assert_eq!(evidence.purpose_id(), "a".repeat(128)); + assert_eq!(evidence.policy_version(), "a".repeat(128)); + let expected_approval = "a".repeat(128); + assert_eq!( + evidence.approval_reference(), + Some(expected_approval.as_str()) ); + assert_eq!(evidence.field_ids(), &["a".repeat(128)]); Ok(()) } @@ -173,10 +183,11 @@ fn exact_maximum_field_set_is_accepted() -> TestResult { input.field_ids = (0..MAX_SENSITIVE_FIELD_COUNT) .map(|index| format!("field:{index}")) .collect(); - assert!( - SensitiveAccessEvidence::try_from(input).is_ok(), - "64 distinct field identifiers are the documented accepted maximum" - ); + let evidence = validated(input)?; + let expected = (0..64) + .map(|index| format!("field:{index}")) + .collect::>(); + assert_eq!(evidence.field_ids(), expected); Ok(()) } diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index e9067c7d0..e2c4b8eaa 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -216,6 +216,8 @@ Network evidence regressions accept exactly 128 query fields, retain every admit Sensitive-access evidence regressions accept the documented exact 128-byte authority-identifier limit and 64 distinct protected-field identifiers. Assert the field-count constant independently against the documented literal 64 so a changed production limit cannot silently resize the accepted fixture. Keep the existing oversized, empty, malformed, and duplicate rejection cases; these receipts contain authority metadata, not protected values or disclosure authority. +At those accepted bounds, compare the exact request, decision, tenant, actor, task, purpose, policy-version and optional approval-reference identifiers, the 128-byte field identifier, and the complete ordered 64-field list returned by the receipt. Independent expected literals must detect truncation after valid admission, not merely successful construction. Isolated producer mutations shorten each 128-byte identifier to 127 bytes or omit the last of 64 fields; every mutation must fail the relevant getter assertion while unchanged production passes. These synthetic checks expose a test-oracle gap, not an observed production defect or a disclosure/broker integration result. + ## 8. Resource and performance tests ### 8.1 Deterministic governor From 4d0262c02ebd519f3d210a32da80151e2830cc1e Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 5 Oct 2026 02:12:05 +0900 Subject: [PATCH 5/5] test(evidence): pin retained boundary receipts and extreme epochs --- CHANGELOG.md | 1 + .../tests/security_review.rs | 37 ++++++++++++++---- .../tests/sensitive_access_evidence.rs | 39 +++++++++++++++++++ docs/TEST_STRATEGY.md | 2 + 4 files changed, 72 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e31680d14..375141d57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to OriginWeave are documented in this file. The format follo - Refreshed the product-gap queue to 126 open pull requests (54 ready, 72 draft) after #190, #188, #185, #192, #182, #184, #115, #181, #116, #117, #118, #183, #114, #127, #112, #109, #186, #110, #108, #111, #174, and #113 were merged into their immediate stacked prerequisites. PRs #147, #146, #145, #144, #143, #142, #141, #139, #136, #132, #129, and #128 moved to ready after exact-head checks and thread review; these are queue-consolidation results, not protected-main shipment. ### Added +- Added test-only exact retained-output assertions for accepted maximum network paths, redacted maximum header metadata, provenance URL/path and locator bytes, extreme sensitive-access timestamps, adjacent retention, and every outcome's optional disclosure time. Unchanged production characterizes first-GREEN; private retained-output corruption probes separately establish sensitivity. No production safety repair, operational retention/deletion, broker integration or release claim is made. - Added regression tests for the exact 128-byte sensitive-access authority identifier and 64-field receipt bounds, including an independent literal assertion that detects field-count constant drift; production validation behavior is unchanged. - Strengthened exact-bound sensitive-access receipts to compare all eight retained authority identifiers, the 128-byte field identifier and all 64 ordered field identifiers. Ten isolated truncation or omission mutations demonstrate regression sensitivity; production evidence validation and disclosure authority are unchanged. - Added an exact 128-query-field network-evidence regression that independently fixes the documented count, checks every retained name/value-redaction pair, and rejects a 129th field; production capture behavior is unchanged. diff --git a/crates/originweave-evidence/tests/security_review.rs b/crates/originweave-evidence/tests/security_review.rs index bfe4af688..72261901e 100644 --- a/crates/originweave-evidence/tests/security_review.rs +++ b/crates/originweave-evidence/tests/security_review.rs @@ -50,10 +50,12 @@ fn adversarial_header_and_query_variants_are_redacted_by_default() { assert!(evidence.query().values().all(|value| value == "[REDACTED]")); } +/// Retain the exact admitted maximum path while rejecting oversized capture inputs. #[test] fn capture_enforces_path_count_and_value_boundaries() { - let maximum_path = format!("/{}", "a".repeat(MAX_PATH_BYTES - 1)); - NetworkEvidence::capture( + assert_eq!(MAX_PATH_BYTES, 4_096); + let maximum_path = format!("/{}", "a".repeat(4_095)); + let maximum_evidence = NetworkEvidence::capture( HttpMethod::Get, origin(), &maximum_path, @@ -61,6 +63,7 @@ fn capture_enforces_path_count_and_value_boundaries() { BTreeMap::new(), ) .expect("path at maximum length"); + assert_eq!(maximum_evidence.path(), maximum_path); assert_eq!( NetworkEvidence::capture( HttpMethod::Get, @@ -153,6 +156,7 @@ fn exact_query_field_limit_preserves_names_and_redacts_values() { ); } +/// Retain the maximum admitted header name with its maximum input value redacted. #[test] fn capture_rejects_invalid_or_oversized_metadata_names() { for invalid_name in [ @@ -173,17 +177,21 @@ fn capture_rejects_invalid_or_oversized_metadata_names() { ); } - NetworkEvidence::capture( + assert_eq!(MAX_METADATA_NAME_BYTES, 256); + assert_eq!(MAX_METADATA_VALUE_BYTES, 8_192); + let exact_name = "x".repeat(256); + let exact_evidence = NetworkEvidence::capture( HttpMethod::Get, origin(), "/", - BTreeMap::from([( - "x".repeat(MAX_METADATA_NAME_BYTES), - "x".repeat(MAX_METADATA_VALUE_BYTES), - )]), + BTreeMap::from([(exact_name.clone(), "x".repeat(8_192))]), BTreeMap::new(), ) .expect("metadata exactly at limits"); + assert_eq!( + exact_evidence.headers(), + &BTreeMap::from([(exact_name, "[REDACTED]".to_owned())]) + ); } #[test] @@ -229,8 +237,23 @@ fn capture_rejects_malformed_percent_escapes_and_ambiguous_segments() { .expect("unambiguous percent encoding"); } +/// Retain exact provenance URL and locator bytes at their independently bounded limits. #[test] fn provenance_text_fields_are_bounded_before_retention() { + assert_eq!(MAX_PROVENANCE_TEXT_BYTES, 8_192); + let exact_url = format!("https://example.com/{}", "a".repeat(4_095)); + let exact_locator = "x".repeat(8_192); + let exact = ProvenanceRecord::new( + &exact_url, + &exact_locator, + VALID_HASH, + EvidenceSourceKind::NetworkResponse, + VerificationResult::Verified, + ) + .expect("maximum path and locator are accepted without truncation"); + assert_eq!(exact.source_url(), exact_url); + assert_eq!(exact.source_locator(), exact_locator); + let oversized_url = format!( "https://example.com/{}", "a".repeat(MAX_PROVENANCE_TEXT_BYTES) diff --git a/crates/originweave-evidence/tests/sensitive_access_evidence.rs b/crates/originweave-evidence/tests/sensitive_access_evidence.rs index 8e9707a0e..955956d13 100644 --- a/crates/originweave-evidence/tests/sensitive_access_evidence.rs +++ b/crates/originweave-evidence/tests/sensitive_access_evidence.rs @@ -191,6 +191,42 @@ fn exact_maximum_field_set_is_accepted() -> TestResult { Ok(()) } +/// Preserve ordinary and adjacent extreme epochs, including the maximum retention deadline. +#[test] +fn maximum_retention_and_adjacent_extreme_epochs_are_retained_exactly() -> TestResult { + let mut maximum_retention = valid_input()?; + maximum_retention.retention_deadline_epoch_seconds = Some(u64::MAX); + let maximum = validated(maximum_retention)?; + assert_eq!(maximum.retention_deadline_epoch_seconds(), Some(u64::MAX)); + + let mut input = valid_input()?; + input.decision_epoch_seconds = u64::MAX - 2; + input.disclosure_epoch_seconds = Some(u64::MAX - 1); + input.retention_deadline_epoch_seconds = Some(u64::MAX); + let evidence = validated(input)?; + assert_eq!(evidence.decision_epoch_seconds(), u64::MAX - 2); + assert_eq!(evidence.disclosure_epoch_seconds(), Some(u64::MAX - 1)); + assert_eq!(evidence.retention_deadline_epoch_seconds(), Some(u64::MAX)); + Ok(()) +} + +/// Preserve simultaneous decision and disclosure with the immediately following retention second. +#[test] +fn equal_decision_and_disclosure_retain_adjacent_retention() -> TestResult { + let mut input = valid_input()?; + input.decision_epoch_seconds = 1_786_176_000; + input.disclosure_epoch_seconds = Some(1_786_176_000); + input.retention_deadline_epoch_seconds = Some(1_786_176_001); + let evidence = validated(input)?; + assert_eq!(evidence.decision_epoch_seconds(), 1_786_176_000); + assert_eq!(evidence.disclosure_epoch_seconds(), Some(1_786_176_000)); + assert_eq!( + evidence.retention_deadline_epoch_seconds(), + Some(1_786_176_001) + ); + Ok(()) +} + #[test] fn disclosure_and_retention_times_fail_closed_when_semantics_are_impossible() -> TestResult { let mut zero_decision = valid_input()?; @@ -231,6 +267,7 @@ fn disclosure_and_retention_times_fail_closed_when_semantics_are_impossible() -> Ok(()) } +/// Preserve the exact optional disclosure timestamp for every documented outcome. #[test] fn every_disclosure_and_control_outcome_has_consistent_lifecycle_semantics() -> TestResult { let outcomes = [ @@ -255,8 +292,10 @@ fn every_disclosure_and_control_outcome_has_consistent_lifecycle_semantics() -> | SensitiveAccessOutcome::HumanApprovalRequired | SensitiveAccessOutcome::DualControlRequired => None, }; + let expected_disclosure = input.disclosure_epoch_seconds; let evidence = validated(input)?; assert_eq!(evidence.outcome(), outcome); + assert_eq!(evidence.disclosure_epoch_seconds(), expected_disclosure); } Ok(()) } diff --git a/docs/TEST_STRATEGY.md b/docs/TEST_STRATEGY.md index e2c4b8eaa..f97a113c2 100644 --- a/docs/TEST_STRATEGY.md +++ b/docs/TEST_STRATEGY.md @@ -218,6 +218,8 @@ Sensitive-access evidence regressions accept the documented exact 128-byte autho At those accepted bounds, compare the exact request, decision, tenant, actor, task, purpose, policy-version and optional approval-reference identifiers, the 128-byte field identifier, and the complete ordered 64-field list returned by the receipt. Independent expected literals must detect truncation after valid admission, not merely successful construction. Isolated producer mutations shorten each 128-byte identifier to 127 bytes or omit the last of 64 fields; every mutation must fail the relevant getter assertion while unchanged production passes. These synthetic checks expose a test-oracle gap, not an observed production defect or a disclosure/broker integration result. +Accepted evidence-retention boundaries also compare the exact 4,096-byte request path, the 256-byte header name paired with a redacted 8,192-byte input value, and provenance source URL/path and 8,192-byte locator bytes. The source URL uses the accepted 4,096-byte path budget, not an assumed 8,192-byte URL acceptance limit. Sensitive-access receipts preserve `u64::MAX` retention, adjacent extreme epochs, equal decision/disclosure times with retention one second later, and each documented outcome's optional disclosure timestamp. These are test-only characterizations of existing constructors and accessors. First-GREEN on unchanged production is not a reproduced production defect; private retained-output corruption probes provide separate sensitivity RED evidence, with production bytes restored exactly. They establish neither operational retention/deletion nor broker, disclosure, browser, hosted-CI or release acceptance. + ## 8. Resource and performance tests ### 8.1 Deterministic governor