RTQ

Security • Evidence Traceability

Verification Traceability

Every security claim links directly to its source file, line numbers, and automated test in the repository at commit e179d2b.

INV-01

Unregistered capability is denied at boundary

CI TESTED

rtq.authorize() checks this.capabilities.get(); missing capability returns code: 'capability.not_registered'.

INV-02

Requested version mismatch is denied

CI TESTED

Exact integer equality check between requested version and registered definition version.

INV-03

Default-deny policy evaluation

CI TESTED

PolicyEngine.evaluate() falls through to decision: 'deny' when no rules match.

INV-04

Authoritative risk: caller claims cannot lower risk

CI TESTED

Risk engine evaluates declared capability metadata; caller claimedRisk downgrade is ignored.

INV-05

Unknown origin escalates authorization

CI TESTED

Untrusted origin 'unknown' is prevented from receiving local automatic approval.

INV-06

High/critical approval strategy is never automatic

CI TESTED

Default strategy resolution mandates human or device confirmation for high/critical risks.

INV-07

Sandbox network deny-by-default with --unshare-net

CI TESTED

bubblewrap argv builder injects --unshare-net and throws if an unsupported network allowlist is requested.

INV-08

Sensitive environment keys stripped from child process

CI TESTED

buildSandboxEnvironment() strips keys matching 'secret', 'token', and 'API_TOKEN'.

INV-09

Single-use tickets: second redemption is rejected

CI TESTED

Atomic status transition from 'issued' to 'redeemed'; subsequent redemption returns code: 'replay'.

INV-10

Ticket signature tamper resistance

CI TESTED

HMAC-SHA256 signature covers canonical JSON ticket representation; modified fields fail verification.

INV-11

Capability version update invalidates outstanding tickets

CI TESTED

Ticket redemption verifies expected capability version against stored ticket version.

INV-12

Approval substitution rejected across challenges

CI TESTED

Cryptographic challenge signature bound to challengeId A cannot authorize challengeId B.