Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
0867aa0
feat(native_handles): add register_scope for live registries
senamakel Oct 23, 2026
1d91ba6
test(crypto): cover scope registration generation checks
senamakel Oct 23, 2026
59ab3d1
fix(tinysecurity-crypto): reject stale scope registrations
senamakel Oct 23, 2026
7994e67
feat(bus): add runtime secret scope registration method
senamakel Oct 23, 2026
4cf86e8
feat(approval): add scope_snapshot accessor for live registrations
senamakel Oct 23, 2026
bef5153
feat(module): support dynamic secret registrations
senamakel Oct 23, 2026
b81f2ca
feat(secret): add dynamic secret scope registration and retirement
senamakel Oct 23, 2026
6694582
feat(module): register secret scopes and retire them with approval sc…
senamakel Oct 23, 2026
1e3896e
refactor(adapter_secret): simplify secret state iteration and borrows
senamakel Oct 23, 2026
5c8eb2e
test(adapter): cover secret scope registration and retirement
senamakel Oct 23, 2026
439fca3
test(adapter-secret): cover mode 22 denial in master resolution test
senamakel Oct 23, 2026
521a9b6
test(adapter-secret): cover runtime secret registration approval scope
senamakel Oct 23, 2026
3d4a58e
test(adapter-secret): simplify mode 22 assertion and fix signature fo…
senamakel Oct 23, 2026
fce7bf3
test(adapter-secret): add trace output to runtime secret exercise
senamakel Oct 23, 2026
a432d47
test(adapter-secret): register approval scope through proxy in runtim…
senamakel Oct 23, 2026
5402803
test(adapter-secret): use hex ids in secret scope fixtures
senamakel Oct 23, 2026
316aa9a
fix(secret): check dynamic registrations before re-registering
senamakel Oct 23, 2026
88c41f4
test(bus): update contract version expectations to 1.29
senamakel Oct 23, 2026
fff0b2a
test(adapter-secret): reformat assertion for readability
senamakel Oct 23, 2026
3456127
test(adapter-secret): cast registration counts to usize
senamakel Oct 23, 2026
37fb952
docs: add runtime secret scopes contract for 1.29
senamakel Oct 23, 2026
4144fad
docs: document runtime secret scopes contract 1.29
senamakel Oct 23, 2026
6fe5572
test(adapter-secret): cover scope replacement and secret re-registration
senamakel Oct 23, 2026
685b4a7
chore(bus): reorder method name entries
senamakel Oct 23, 2026
4de953e
test(crypto): cover scope replacement fencing old reservations
senamakel Oct 23, 2026
b3dee49
feat(native_handles): add replace_scope to update a live scope's policy
senamakel Oct 23, 2026
9788ae1
fix(secret): guard approval scope with rwlock and refresh on change
senamakel Oct 23, 2026
826b48b
fix(module): refresh approval scope after replacing it
senamakel Oct 23, 2026
84299f1
style: reformat adapter_secret for rustfmt compliance
senamakel Oct 23, 2026
1a6b62e
test(adapter-secret): cover re-registration with a reused policy ref
senamakel Oct 23, 2026
2f98856
fix(native_handles): reject operations on deactivated scopes
senamakel Oct 23, 2026
f0a7354
test(crypto): cover revoked scope re-registration and replacement
senamakel Oct 23, 2026
48ce317
test(crypto): reformat revoked scope assertions
senamakel Oct 23, 2026
8c7ec6e
docs(specs): document tombstoning of revoked runtime secret ids
senamakel Oct 23, 2026
4653dbf
refactor(crypto): take registration by reference in replace_scope
senamakel Oct 23, 2026
e507098
fix(tinysecurity-crypto): correct borrows in native handle registry
senamakel Oct 23, 2026
469a801
fix(tinysecurity-crypto): correct registration reference in scope checks
senamakel Oct 23, 2026
4bf677c
chore(adapter): note async bus interface in secret scope registration
senamakel Oct 23, 2026
e7347bc
refactor(adapter_secret): simplify scope retention predicate
senamakel Oct 23, 2026
0e3d8fd
fix(adapter): serialize secret scope lifecycle operations
senamakel Oct 23, 2026
c6fc837
fix(tinysecurity-module): retire approval scopes after engine updates
senamakel Oct 23, 2026
0a2badb
fix(tinysecurity-module): retire approval scope before replacing or r…
senamakel Oct 23, 2026
802648b
refactor(adapter): move secret scope lifecycle lock to a static
senamakel Oct 23, 2026
74fbe99
fix(tinysecurity-module): retire approval scope after engine call
senamakel Oct 23, 2026
aeeb66c
fix(adapter): serialize secret scope registration with lifecycle lock
senamakel Oct 23, 2026
9968f23
fix(adapter): serialize scope registration and retirement
senamakel Oct 23, 2026
3eb7e6a
style: reformat approval scope code and tests
senamakel Oct 23, 2026
88f5c4f
test(policy): cover host skill scan verdicts and denial precedence
senamakel Oct 23, 2026
dae1135
feat(bus): add skill scan verdict check to policy contract
senamakel Oct 23, 2026
f205ed7
fix(approval): treat skill scan checks as non-external
senamakel Oct 23, 2026
f6256bb
test(policy): import SkillScanVerdict in engine tests
senamakel Oct 23, 2026
9a950f5
test(tinysecurity-policy): rename loop variable in skill scan verdict…
senamakel Oct 23, 2026
fecf3bc
feat(policy): bind skill scan approvals to bundle digest
senamakel Oct 23, 2026
893ef9c
docs: document host skill-scan contract 1.29
senamakel Oct 23, 2026
5c4abe5
test(approval): cover skill scan warn and block verdicts
senamakel Oct 23, 2026
b8be187
test(approval): assert denied lifecycle state instead of error
senamakel Oct 23, 2026
d2d1187
test(approval): narrow skill scan test to human approval path
senamakel Oct 23, 2026
5599b28
docs: expand skill-scan contract 1.29 spec
senamakel Oct 23, 2026
a5fdecc
test(approval): cover skill scan block under auto-approve scope
senamakel Oct 23, 2026
09fdf07
fix(approval): require human approval for blocked and warned skill scans
senamakel Oct 23, 2026
2237f3b
test(adapter-host): cover host skill scan verdicts before run_workflow
senamakel Oct 23, 2026
758a779
refactor(approval): extract blocked skill scan check and flatten cond…
senamakel Oct 23, 2026
e94c723
test(policy): cover skill scan pass without effect check
senamakel Oct 23, 2026
4adef47
fix(policy): stop treating skill scan checks as host tool calls
senamakel Oct 23, 2026
2f85664
docs: clarify skill scan is supplemental and additive for 1.28 hosts
senamakel Oct 23, 2026
8dfbb39
test(policy): simplify contract version test setup
senamakel Oct 23, 2026
7721860
test(adapter-host-tool): cover skill scan checks in admission-only de…
senamakel Oct 23, 2026
d9d2590
fix(adapter): treat skill scans as admission-only checks
senamakel Oct 23, 2026
24ef88e
style: reformat admission_only check for readability
senamakel Oct 23, 2026
0e8e631
docs(tinysecurity-module): clarify admission_only doc comment
senamakel Oct 23, 2026
e7f1b32
test: isolate process-owned confidential fixtures in child processes
senamakel Oct 23, 2026
fe5bf95
test(adapter-secret): cover static registration and conflicting backend
senamakel Oct 23, 2026
4af2af2
style: format runtime registration coverage tests
senamakel Oct 23, 2026
10453d7
fix(secret): refresh cipher audit policy on scope replacement
senamakel Oct 23, 2026
44499c4
chore(tinysecurity-module): gate audit_policy_ref behind cfg(test)
senamakel Oct 23, 2026
e71c68c
test(adapter): serialize secret scope tests with a shared lock
senamakel Oct 23, 2026
ca5b4d0
test(adapter): isolate process-global secret scope tests
senamakel Oct 23, 2026
5227651
test(adapter-secret): drop redundant lock and inline result type
senamakel Oct 23, 2026
6ddd02a
fix(module): pass secret cipher state into approval scope refresh
senamakel Oct 23, 2026
57cc91c
test: remove process isolation helper from secret adapter tests
senamakel Oct 23, 2026
d57aafa
Merge branch 'skill-scan-risk-7328' into runtime-secret-scopes-129
senamakel Oct 23, 2026
f391368
test(secret): cover orphaned pending scope cleanup
senamakel Oct 23, 2026
6458de1
fix(secret): prune orphaned pending scope calls
senamakel Oct 23, 2026
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
3 changes: 3 additions & 0 deletions MODULE.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,9 @@ Full details: [paired-device lifecycle specification](docs/specs/device-pairing-
## Browser destination authorization (contract 1.28)
Full details: [browser dial specification](docs/specs/browser-dial-contract-1.28.md).

## Host skill-scan decisions (contract 1.29)
Full details: [host skill-scan specification](docs/specs/skill-scan-contract-1.29.md).

## Confidential injected master resolution
Full details: [`Confidential injected master resolution`](docs/module-crypto.md#confidential-injected-master-resolution).

Expand Down
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,17 @@ when a lease expires or policy generation changes. Sensitive and local-only
privacy modes deny this uninspectable traffic; TinyComputer remains responsible
for enforcing the proxy and dialing the approved socket. See the
[browser-dial contract specification](docs/specs/browser-dial-contract-1.28.md).
Contract 1.29 adds the host-only `RegisterSecretScope2` member for adding a
secret resolver bound to an already-live approval scope, without reinitializing
the process-global secret registry. Approval-scope replacement or retirement
revokes the associated secret handles and runtime registrations; see the
[runtime secret-scope specification](docs/specs/runtime-secret-scopes-contract-1.29.md).

Contract 1.29 adds `Check::SkillScan` so the trusted host can submit the scan
verdict and exact bundle digest before an installed skill runs. `Block` is a
content denial, `Warn` enters the host's approval flow, and `Pass` leaves the
remaining policy checks authoritative. See the
[host skill-scan specification](docs/specs/skill-scan-contract-1.29.md).

Contract 1.6 supplies `Audit2`, `EvaluateAudited2` and `CheckAudited2` with
authenticated exact audit callbacks and a bounded [native journal](crates/tinysecurity-audit/README.md).
Expand Down
16 changes: 15 additions & 1 deletion crates/tinysecurity-approval/src/binding.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,19 @@ pub(crate) fn native_safe_call(request: &EvaluateRequest) -> Result<String> {
}
Ok(safe_call)
}

fn contains_blocked_skill_scan(checks: &[Check]) -> bool {
checks.iter().any(|check| {
matches!(
check,
Check::SkillScan {
verdict: tinysecurity_bus::SkillScanVerdict::Block,
..
}
)
})
}

pub(crate) fn original(
reg: &ApprovalScope2,
request: &EvaluateRequest,
Expand All @@ -113,6 +126,7 @@ pub(crate) fn original(
|| request.call.arguments_json.len() > 32768
|| request.call.checks.is_empty()
|| request.call.checks.len() > 128
|| contains_blocked_skill_scan(&request.call.checks)
|| (reg.ceiling == AccessTier::Read && request.caller.tier != AccessTier::Read)
|| (reg.ceiling == AccessTier::Write && request.caller.tier == AccessTier::Full)
|| request
Expand All @@ -137,7 +151,7 @@ pub(crate) fn original(
args.sort_all_objects();
let canonical = serde_json::to_string(&args).map_err(|_| Error::Invalid)?;
let external = request.call.checks.iter().any(|check| match check {
Check::LocalDiagnostic {} => false,
Check::LocalDiagnostic {} | Check::SkillScan { .. } => false,
Check::Path { write, .. } => *write,
Check::HostAction {
external_effect, ..
Expand Down
18 changes: 18 additions & 0 deletions crates/tinysecurity-approval/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -760,7 +760,17 @@ impl Engine {
now: u64,
native: bool,
) -> Result<(Option<ApprovalRow2>, bool)> {
let scan_warning = request.request.call.checks.iter().any(|check| {
matches!(
check,
Check::SkillScan {
verdict: tinysecurity_bus::SkillScanVerdict::Warn,
..
}
)
});
let human_only = native
|| scan_warning
|| matches!(
request.request.call.tool.as_str(),
"sandbox_host_network" | "device_crypto"
Expand Down Expand Up @@ -1172,6 +1182,14 @@ impl Engine {
let entry = self.entry(id)?;
Ok(self.registered(&entry))
}
/// Return the current trusted scope snapshot for one live registration.
/// This is used by sibling module adapters that must bind a secondary
/// capability to the approval engine's canonical subject and generation.
/// # Errors
/// Rejects unknown registrations or poisoned approval state.
pub fn scope_snapshot(&self, id: &str) -> Result<ApprovalScope2> {
self.registration(id)
}
fn validate_scope(scope: &ApprovalScope2) -> Result<()> {
if scope.scope_id.len() != 32
|| !scope.scope_id.bytes().all(|b| b.is_ascii_hexdigit())
Expand Down
27 changes: 27 additions & 0 deletions crates/tinysecurity-approval/src/engine_scopes_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,33 @@ async fn host_tool_marker_is_an_external_effect_that_cron_cannot_reach() -> Resu
Ok(())
}

#[tokio::test]
async fn skill_scan_warning_enters_human_approval() -> Result<()> {
let (_, owner) = owner()?;
let mut auto_approve = register(7);
auto_approve.scope.auto_approve_all = true;
auto_approve.grants = grants(&["run_workflow"], &[]);
owner.register_scope(auto_approve).await?;

let mut warning = begin_for(7, "run_workflow", None, Origin::Operator);
warning.request.call.checks = vec![Check::SkillScan {
verdict: tinysecurity_bus::SkillScanVerdict::Warn,
bundle_sha256: "a".repeat(64),
}];
let pending = owner.begin(warning).await?;
assert_eq!(pending.state, ApprovalLifecycle2::Pending);
assert!(!pending.external_effect);

let mut blocked = begin_for(7, "run_workflow", None, Origin::Operator);
blocked.request.caller.call_id = "blocked-call".into();
blocked.request.call.checks = vec![Check::SkillScan {
verdict: tinysecurity_bus::SkillScanVerdict::Block,
bundle_sha256: "b".repeat(64),
}];
assert_eq!(owner.begin(blocked).await.err(), Some(Error::Denied));
Ok(())
}

#[tokio::test]
async fn host_action_and_shell_checks_bind_with_their_own_external_effect() -> Result<()> {
let (_, owner) = owner()?;
Expand Down
2 changes: 1 addition & 1 deletion crates/tinysecurity-bus/src/device_frame_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,5 +70,5 @@ fn frame_operations_redact_both_payloads_without_changing_open_wire_shape()
#[test]
fn frame_member_name_is_stable_and_contract_version_is_bumped() {
assert_eq!(crate::names::methods::DEVICE_FRAME2, "DeviceFrame2");
assert_eq!(crate::CONTRACT_VERSION, (1, 28));
assert_eq!(crate::CONTRACT_VERSION, (1, 29));
}
2 changes: 1 addition & 1 deletion crates/tinysecurity-bus/src/device_pairing_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fn refresh_and_close_are_distinct_transient_session_operations() {

#[test]
fn pairing_contract_is_versioned_after_the_frame_contract() {
assert_eq!(CONTRACT_VERSION, (1, 28));
assert_eq!(CONTRACT_VERSION, (1, 29));
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion crates/tinysecurity-bus/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub use scoped_policy::*;
pub use tool_trust::*;
pub mod names;
/// Current wire vocabulary version, independent of the artifact version.
pub const CONTRACT_VERSION: (u32, u32) = (1, 28);
pub const CONTRACT_VERSION: (u32, u32) = (1, 29);
/// Whether a remote module's advertised version supplies this host's vocabulary.
///
/// `version` is the provider version received by the host, not a host requirement
Expand Down
3 changes: 3 additions & 0 deletions crates/tinysecurity-bus/src/names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ pub mod methods {
pub const REPLACE_APPROVAL_SCOPE2: &str = "ReplaceApprovalScope2";
/// Retire a scope so later calls under it deny (contract 1.17).
pub const RETIRE_APPROVAL_SCOPE2: &str = "RetireApprovalScope2";
/// Register a secret resolver for an already-live approval scope (contract 1.29).
pub const REGISTER_SECRET_SCOPE2: &str = "RegisterSecretScope2";
/// Evaluate member.
pub const EVALUATE: &str = "Evaluate";
/// Check member.
Expand Down Expand Up @@ -249,6 +251,7 @@ pub const METHODS: &[&str] = &[
methods::LIST_TOOL_TRUST2,
methods::IMPORT_TRUST_SOURCE2,
methods::REGISTER_APPROVAL_SCOPE2,
methods::REGISTER_SECRET_SCOPE2,
methods::REPLACE_APPROVAL_SCOPE2,
methods::RETIRE_APPROVAL_SCOPE2,
methods::REGISTER_SANDBOX_SCOPE2,
Expand Down
25 changes: 25 additions & 0 deletions crates/tinysecurity-bus/src/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ pub struct ToolCall {
/// Never forward checks supplied by a model, tool client or remote caller.
pub checks: Vec<Check>,
}

/// Host-computed verdict from scanning a skill before execution (contract 1.29).
/// The host must scan the exact installed document and resources it will expose;
/// this value is a trusted host assertion, never a model-supplied claim. It is
/// supplemental to the host-effect check and cannot authorize a tool call alone.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum SkillScanVerdict {
/// No findings require action.
Pass,
/// Findings require the existing host approval flow before execution.
Warn,
/// The scan found content that must not execute.
Block,
}

/// A check of a concrete operation. The bootstrap has no URL authorization.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case", deny_unknown_fields)]
Expand Down Expand Up @@ -141,6 +157,15 @@ pub enum Check {
#[serde(default, skip_serializing_if = "Option::is_none")]
command_policy: Option<CommandPolicyId>,
},
/// A trusted host's scan result for the exact skill bundle being executed
/// (contract 1.29). `Warn` requires host approval; `Block` is a hard denial.
SkillScan {
/// Result computed by the host scanner.
verdict: SkillScanVerdict,
/// Lowercase SHA-256 of the exact document and resources the host will
/// expose during this run. The approval binding includes this value.
bundle_sha256: String,
},
/// An effect not supported by this engine.
Unknown {
/// Content-free descriptor.
Expand Down
25 changes: 25 additions & 0 deletions crates/tinysecurity-bus/src/policy_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,31 @@ fn host_shell_has_a_stable_strict_wire_form() -> TestResult {
Ok(())
}

#[test]
fn skill_scan_has_stable_verdict_wire_forms() -> TestResult {
for (verdict, wire) in [
(SkillScanVerdict::Pass, "pass"),
(SkillScanVerdict::Warn, "warn"),
(SkillScanVerdict::Block, "block"),
] {
let check = Check::SkillScan {
verdict,
bundle_sha256: "a".repeat(64),
};
let value = serde_json::to_value(&check)?;
assert_eq!(
value,
serde_json::json!({
"kind":"skill_scan",
"verdict":wire,
"bundle_sha256":"a".repeat(64),
})
);
assert_eq!(serde_json::from_value::<Check>(value)?, check);
}
Ok(())
}

#[test]
fn new_denial_reasons_have_stable_wire_forms_and_old_ones_are_unchanged() -> TestResult {
for (reason, wire) in [
Expand Down
16 changes: 16 additions & 0 deletions crates/tinysecurity-bus/src/secret.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,22 @@ pub struct SecretRegistration2 {
/// At most three compatible read-only historical entries.
pub legacy: Vec<SecretSourceBinding2>,
}
/// Host-only runtime registration for a secret scope whose approval scope is live.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct RegisterSecretScopeRequest2 {
/// Immutable secret registration; the module resolves the approval scope itself.
pub registration: SecretRegistration2,
}
/// Safe confirmation of one active secret registration.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SecretScopeReceipt2 {
/// Opaque registration identity supplied by the trusted host.
pub registration_id: String,
/// Whether the registration is currently active.
pub active: bool,
}
/// Bounded retention and reservation ceilings, matching the internal registry.
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
Expand Down
35 changes: 35 additions & 0 deletions crates/tinysecurity-bus/src/secret_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,38 @@ fn caller_authority_overrides_and_plaintext_response_fields_are_rejected()
);
Ok(())
}

#[test]
fn runtime_secret_scope_registration_only_accepts_the_trusted_descriptor()
-> Result<(), Box<dyn std::error::Error>> {
let request = RegisterSecretScopeRequest2 {
registration: SecretRegistration2 {
registration_id: "a".repeat(32),
approval_scope_id: "b".repeat(32),
origin: Origin::Operator,
purpose: MasterPurpose2::ConfigUserMaster,
target: SecretBinding2 {
backend_id: "c".repeat(32),
slot: MasterSlotKind2::User,
},
legacy: vec![],
},
};
let value = serde_json::to_value(&request)?;
assert_eq!(
serde_json::from_value::<RegisterSecretScopeRequest2>(value.clone())?,
request
);
let mut forged = value;
forged["subject"] = serde_json::json!({ "user": "caller" });
assert!(serde_json::from_value::<RegisterSecretScopeRequest2>(forged).is_err());
let receipt = SecretScopeReceipt2 {
registration_id: "a".repeat(32),
active: true,
};
assert_eq!(
serde_json::from_value::<SecretScopeReceipt2>(serde_json::to_value(receipt.clone())?)?,
receipt
);
Ok(())
}
11 changes: 6 additions & 5 deletions crates/tinysecurity-bus/tests/scoped_wire.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Registered subject policy wire shapes and the 1.28 compatibility boundary.
//! Registered subject policy wire shapes and the 1.29 compatibility boundary.
use serde_json::json;
use tinysecurity_bus::*;

Expand Down Expand Up @@ -79,6 +79,7 @@ fn new_members_are_advertised_and_named_by_contract_constants() {
names::methods::AUTHORIZE_BROWSER_DIAL,
names::methods::CONSUME_BROWSER_DIAL,
names::methods::VALIDATE_BROWSER_DIAL,
names::methods::REGISTER_SECRET_SCOPE2,
] {
assert!(names::METHODS.contains(&name), "{name}");
}
Expand All @@ -87,10 +88,10 @@ fn new_members_are_advertised_and_named_by_contract_constants() {

#[test]
fn contract_bump_is_additive_for_older_hosts_and_modules() {
assert_eq!(CONTRACT_VERSION, (1, 28));
// A host built against 1.28 accepts this module and newer minors, not a 1.27 module.
assert!(is_compatible((1, 28)));
assert!(!is_compatible((1, 27)));
assert_eq!(CONTRACT_VERSION, (1, 29));
// A host built against 1.29 accepts this module and newer minors, not a 1.28 module.
assert!(is_compatible((1, 29)));
assert!(!is_compatible((1, 28)));
assert!(!is_compatible((1, 26)));
assert!(!is_compatible((1, 25)));
assert!(!is_compatible((1, 24)));
Expand Down
2 changes: 1 addition & 1 deletion crates/tinysecurity-bus/tests/wire.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ fn redactor_init_is_additive_and_secrets_never_enter_public_info()
serde_json::to_value(&config)?["redactor"]["secrets"][0],
"literal-private"
);
assert_eq!(CONTRACT_VERSION, (1, 28));
assert_eq!(CONTRACT_VERSION, (1, 29));
for (mode, wire) in [
(RedactMode::Text, "text"),
(RedactMode::StructuredArguments, "structured_arguments"),
Expand Down
Loading
Loading