From acd9b8cfd90d7d8f29a037f901d863ea7db5dfa6 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Jul 2026 23:43:25 +0000 Subject: [PATCH 1/4] docs(status): reconcile dashboards to the honest Grade-D/60% state TOPOLOGY.md advertised "OVERALL 100% v1.0 Production Ready" and per- component 100%s ("MPR security by construction proven", "audit trail validated") while STATE.a2ml records completion 60% / CRG grade D and READINESS.md grades the project D (Alpha, Unstable). This is the "dashboard that lies" pattern. - Rewrite the completion dashboard to summarise STATE.a2ml / READINESS.md (60%, Grade D), naming the real caveats: homerolled attestation MAC, label-only Ed25519/X25519, obliteration not guaranteed on SSD/CoW, formal proofs pending and unlinked to the Rust. - Add a prominent ARCHIVED banner to TESTING-REPORT.adoc (a stale 2025-12-29 snapshot whose "all tests passed / robust" framing overstates current status), pointing readers to READINESS.md / STATE.a2ml. No code changes; documentation truthfulness only. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_015qwVESTcbfanY2iJPQNoSz --- TESTING-REPORT.adoc | 16 ++++++++++++++-- TOPOLOGY.md | 40 ++++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 14 deletions(-) diff --git a/TESTING-REPORT.adoc b/TESTING-REPORT.adoc index 1b28911..a974b79 100644 --- a/TESTING-REPORT.adoc +++ b/TESTING-REPORT.adoc @@ -2,15 +2,27 @@ // Copyright (c) Jonathan D.A. Jewell // SPDX-FileCopyrightText: 2025 Jonathan D.A. Jewell -= JanusKey Testing Report += JanusKey Testing Report (ARCHIVED — 2025-12-29) :toc: auto :icons: font :source-highlighter: rouge :date: 2025-12-29 +[WARNING] +==== +*This report is a stale snapshot from 2025-12-29 and is retained for +history only.* It predates the 2026-04 readiness assessment, which graded +the project *D (Alpha, Unstable)*. Its "all tests passed / robust and +functional" framing overstates the current state (homerolled attestation +MAC, unimplemented asymmetric crypto, no fuzz/mutation/chaos testing). + +*For the current, authoritative test status see `READINESS.md` and +`.machine_readable/6a2/STATE.a2ml`.* +==== + == Executive Summary -This report documents the comprehensive testing of the JanusKey project, a reversible file operations system with cryptographic key management. All tests passed successfully, demonstrating a robust and functional implementation. +This report documents the testing of the JanusKey project as of 2025-12-29, a reversible file operations system with cryptographic key management. The tests recorded here passed at that time; see the archival warning above for why this no longer reflects project status. |=== | Metric | Result diff --git a/TOPOLOGY.md b/TOPOLOGY.md index 3da509b..020e00d 100644 --- a/TOPOLOGY.md +++ b/TOPOLOGY.md @@ -3,7 +3,7 @@ SPDX-License-Identifier: CC-BY-SA-4.0 Copyright (c) Jonathan D.A. Jewell --> - + # JanusKey — Project Topology @@ -53,27 +53,43 @@ Copyright (c) Jonathan D.A. Jewell ## Completion Dashboard +> **Source of truth:** `.machine_readable/6a2/STATE.a2ml` (completion 60%, +> CRG grade **D**) and `READINESS.md` (Grade **D — Alpha, Unstable**). This +> dashboard is a human-readable summary of those files; if they disagree, +> they win. Percentages below are qualitative, not measured coverage. + ``` COMPONENT STATUS NOTES ───────────────────────────────── ────────────────── ───────────────────────────────── CORE ENGINE (RUST) - Operation Layer ██████████ 100% Delete/Modify/Move stable - Inverse Metadata Gen ██████████ 100% Perfect inversion verified - Transaction Manager ██████████ 100% Begin/Commit/Rollback active - Content-Addressed Storage ██████████ 100% SHA256 deduplication verified + Operation Layer ████████░░ ~85% Delete/Modify/Move implemented; unit-tested + Inverse Metadata Gen ████████░░ ~80% execute∘undo roundtrip property-tested (proptest) + Transaction Manager ████████░░ ~80% Begin/Commit/Rollback tested via P2P suite + Content-Addressed Storage ████████░░ ~85% Real SHA256 content store + dedup + +SECURITY (honest) + Attestation / audit chain ███░░░░░░░ ~30% Homerolled SHA256(key||data||prev) MAC + + zero-key fallback — flagged by threat model + (STATE.a2ml homerolled-hmac); needs real HMAC + Asymmetric crypto █░░░░░░░░░ ~10% Ed25519/X25519 are enum labels, not implemented + Secure obliteration ████░░░░░░ ~40% Best-effort; NOT guaranteed on SSD/CoW (threat- + model dependent — see obliteration caveat) INTERFACES & RESEARCH - CLI Interface (jk) ██████████ 100% Full command set verified - MPR Methodology ██████████ 100% Security by construction proven - Testing Report (SCM) ██████████ 100% Audit trail validated + CLI Interface (jk) ████████░░ ~85% Full command set; no user testing yet + MPR Methodology ████░░░░░░ ~40% Design documented; FORMAL PROOFS PENDING + (30 Idris2 proofs unchecked in CI; not linked + to the Rust) + Testing (READINESS matrix) ██████░░░░ ~60% 67 tests + 5 benches; missing fuzz, mutation, + chaos, compatibility (Grade D) REPO INFRASTRUCTURE - Justfile Automation ██████████ 100% Standard build/lint tasks - .machine_readable/ ██████████ 100% STATE tracking active - 0-AI-MANIFEST.a2ml ██████████ 100% AI entry point verified + Justfile Automation █████████░ ~90% Build/lint/test recipes present + .machine_readable/ █████████░ ~90% STATE tracking active + 0-AI-MANIFEST.a2ml █████████░ ~90% AI entry point present ───────────────────────────────────────────────────────────────────────────── -OVERALL: ██████████ 100% v1.0 Production Ready +OVERALL: ██████░░░░ ~60% Grade D — Alpha, Unstable (not v1.0) ``` ## Key Dependencies From 69c303f972ba978e0c5dff9fd1da6b4601a06c40 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 2 Jul 2026 23:48:47 +0000 Subject: [PATCH 2/4] fix(crypto): use real HMAC-SHA256 for attestations; refuse fake asymmetric keys MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two honesty/security fixes flagged by the threat model and STATE.a2ml. B3 — attestation MAC: - Replace the homerolled `SHA256(key || data || previous_hash)` (not a MAC; banned by the Trustfile `no-homerolled-hmac` invariant) with a real HMAC-SHA256 via the `hmac` crate (RFC 2104), with a versioned scheme label bound in as a domain separator (januskey.attestation.HMAC-SHA256.v1). - `compute_attestation` now returns Result and hard-errors when no key is set, removing the `unwrap_or([0u8; 32])` all-zero-key fallback that silently produced forgeable, unkeyed attestations. - Producer (log_event) and verifier (verify_integrity) both propagate the error, so they stay consistent. B4 — fake asymmetric crypto: - `SecretKey::generate()` only ever produces 32 random bytes and ignores the algorithm, so selecting ed25519/x25519 yielded a random blob merely labelled "Ed25519"/"X25519" — not a keypair. Refuse generation of these types at the CLI with a clear "not implemented" error. Enum variants are retained (documented as reserved/unimplemented) so historical serialized metadata and audit entries still deserialize. Regression tests added: test_attestation_refused_without_key, test_attestation_is_genuinely_keyed (wrong key fails verification — a plain hash would not catch this, proving the MAC is genuinely keyed). Verified: `cargo build -p januskey` clean; `cargo test -p januskey --lib` 26 passed / 0 failed; attestation E2E + P2P chain-integrity tests pass. STATE.a2ml blockers updated (homerolled-hmac RESOLVED). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_015qwVESTcbfanY2iJPQNoSz --- .machine_readable/6a2/STATE.a2ml | 4 +- Cargo.lock | 10 +++ crates/januskey-cli/Cargo.toml | 1 + crates/januskey-cli/src/attestation.rs | 101 ++++++++++++++++++++++--- crates/januskey-cli/src/keys.rs | 7 ++ crates/januskey-cli/src/keys_cli.rs | 18 +++-- 6 files changed, 122 insertions(+), 19 deletions(-) diff --git a/.machine_readable/6a2/STATE.a2ml b/.machine_readable/6a2/STATE.a2ml index 13bdcf4..dfe9cd1 100644 --- a/.machine_readable/6a2/STATE.a2ml +++ b/.machine_readable/6a2/STATE.a2ml @@ -53,8 +53,8 @@ compatibility = false [blockers] threat-model-signoff = "threat-model.a2ml status = draft-pending-human-review (since 2026-04-19); blocks any januskey-mcp cartridge" -homerolled-hmac = "attestation.rs SHA256(key||data) pattern flagged by threat model; must be replaced with a real HMAC primitive before MCP exposure (Trustfile no-homerolled-hmac)" -metadata-only-key-types = "Ed25519/X25519 enum entries lack real sign/DH implementations (threat-model flag)" +homerolled-hmac = "RESOLVED: attestation.rs now uses a real HMAC-SHA256 (hmac crate, RFC 2104) with a versioned domain separator, and hard-errors instead of the unwrap_or([0u8;32]) unkeyed fallback. Regression tests: test_attestation_refused_without_key, test_attestation_is_genuinely_keyed. Satisfies Trustfile no-homerolled-hmac." +metadata-only-key-types = "PARTIALLY MITIGATED: Ed25519/X25519 key generation is now refused at the CLI (was silently producing 32 random bytes mislabelled as an asymmetric key); enum variants retained only for backward-compatible deserialization. Real dalek-backed sign/DH still unimplemented." claude-md-maintainer-edits = ".claude/CLAUDE.md is guardrail-blocked for agents: line 46 still says 'Julia/Rust/ReScript' (leftover from #49); package-management section still cites flake.nix, removed by the estate wave" idris2-in-ci = "just test-proofs requires the idris2 binary; proof check not yet wired as a CI gate (READINESS D→C promotion item)" diff --git a/Cargo.lock b/Cargo.lock index 4962f81..073449e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -700,6 +700,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "iana-time-zone" version = "0.1.65" @@ -796,6 +805,7 @@ dependencies = [ "flate2", "glob", "hex", + "hmac", "indicatif", "predicates", "proptest", diff --git a/crates/januskey-cli/Cargo.toml b/crates/januskey-cli/Cargo.toml index c68530b..80a3f50 100644 --- a/crates/januskey-cli/Cargo.toml +++ b/crates/januskey-cli/Cargo.toml @@ -18,6 +18,7 @@ clap = { version = "4", features = ["derive"] } serde = { version = "1", features = ["derive"] } serde_json = "1" sha2 = "0.10" +hmac = "0.12" chrono = { version = "0.4", features = ["serde"] } uuid = { version = "1", features = ["v4", "serde"] } thiserror = "1" diff --git a/crates/januskey-cli/src/attestation.rs b/crates/januskey-cli/src/attestation.rs index 8928382..daf7e46 100644 --- a/crates/januskey-cli/src/attestation.rs +++ b/crates/januskey-cli/src/attestation.rs @@ -6,6 +6,7 @@ // Tamper-evident logging with cryptographic attestations use chrono::{DateTime, Utc}; +use hmac::{Hmac, Mac}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::fs::{self, File, OpenOptions}; @@ -118,6 +119,10 @@ pub struct AuditLog { } impl AuditLog { + /// Domain-separation / version label bound into every attestation MAC. + /// Bumping this string invalidates prior attestations by construction. + const ATTESTATION_SCHEME: &'static str = "januskey.attestation.HMAC-SHA256.v1"; + /// Create audit log manager for a directory pub fn new(root: &Path) -> Self { let log_path = root.join(".januskey").join("keys").join("audit.log"); @@ -179,16 +184,43 @@ impl AuditLog { .unwrap_or_else(|| "0".repeat(64))) } - /// Compute HMAC-SHA256 attestation - fn compute_attestation(&self, data: &str, previous_hash: &str) -> String { - let key = self.attestation_key.unwrap_or([0u8; 32]); - - // Simple HMAC-SHA256: H(key || data || previous_hash) - let mut hasher = Sha256::new(); - hasher.update(&key); - hasher.update(data.as_bytes()); - hasher.update(previous_hash.as_bytes()); - hex::encode(hasher.finalize()) + /// Compute the attestation MAC for a log entry. + /// + /// Uses a real HMAC-SHA256 (RFC 2104) via the `hmac` crate, keyed on the + /// store-derived attestation key. This replaces the former homerolled + /// `SHA256(key || data || previous_hash)` construction, which was not a + /// MAC (length-extension–exposed and banned by the Trustfile + /// `no-homerolled-hmac` invariant). + /// + /// The scheme label is bound into the MAC as a domain separator; it + /// versions the construction, so entries written under the old homerolled + /// scheme will not verify under this one (an intentional, alpha-stage + /// breaking change — see the module changelog / STATE.a2ml). + /// + /// Errors if no attestation key is set: an unkeyed attestation is + /// forgeable and must never be silently produced (the previous + /// `unwrap_or([0u8; 32])` all-zero-key fallback did exactly that). + fn compute_attestation( + &self, + data: &str, + previous_hash: &str, + ) -> std::io::Result { + let key = self.attestation_key.ok_or_else(|| { + std::io::Error::new( + std::io::ErrorKind::PermissionDenied, + "attestation key not set; refusing to produce an unkeyed \ + (forgeable) attestation — call init()/set_attestation_key() first", + ) + })?; + + let mut mac = >::new_from_slice(&key) + .expect("HMAC accepts keys of any length"); + mac.update(Self::ATTESTATION_SCHEME.as_bytes()); + mac.update(b"\x00"); + mac.update(data.as_bytes()); + mac.update(b"\x00"); + mac.update(previous_hash.as_bytes()); + Ok(hex::encode(mac.finalize().into_bytes())) } /// Log an event @@ -211,7 +243,7 @@ impl AuditLog { event_type, actor ); - let attestation = self.compute_attestation(&attestation_data, &previous_hash); + let attestation = self.compute_attestation(&attestation_data, &previous_hash)?; let entry = AuditEntry { event_id, @@ -408,7 +440,7 @@ impl AuditLog { entry.actor ); let expected_attestation = - self.compute_attestation(&attestation_data, &entry.previous_hash); + self.compute_attestation(&attestation_data, &entry.previous_hash)?; if entry.attestation != expected_attestation { return Ok(IntegrityReport { @@ -552,4 +584,49 @@ mod tests { .expect("failed to get key history"); assert_eq!(history.len(), 3); } + + #[test] + fn test_attestation_refused_without_key() { + // An AuditLog with no attestation key must refuse to produce an + // attestation rather than silently sign with an all-zero key + // (the former unwrap_or([0u8; 32]) forgery hazard). + let tmp = TempDir::new().expect("failed to create temp dir"); + let log = AuditLog::new(tmp.path()); // note: no init()/set_attestation_key() + + let err = log + .log_store_init() + .expect_err("logging without a key must fail"); + assert_eq!(err.kind(), std::io::ErrorKind::PermissionDenied); + } + + #[test] + fn test_attestation_is_genuinely_keyed() { + // Verifying with the wrong key must fail. A plain unkeyed hash would + // still "verify" here; only a real keyed MAC catches this, proving the + // attestation is HMAC-keyed and not the old homerolled concatenation. + let tmp = TempDir::new().expect("failed to create temp dir"); + + { + let mut log = AuditLog::new(tmp.path()); + log.init([7u8; 32]).expect("init"); + log.log_store_init().expect("log"); + log.log_key_generated( + Uuid::new_v4(), + "fp", + KeyAlgorithm::Aes256Gcm, + KeyPurpose::Encryption, + ) + .expect("log"); + assert!(log.verify_integrity().expect("verify").valid); + } + + // Re-open the same log with a DIFFERENT attestation key. + let mut wrong = AuditLog::new(tmp.path()); + wrong.set_attestation_key([9u8; 32]); + let report = wrong.verify_integrity().expect("verify"); + assert!( + !report.valid, + "verification must fail under a different key (keyed MAC)" + ); + } } diff --git a/crates/januskey-cli/src/keys.rs b/crates/januskey-cli/src/keys.rs index 3cb1326..19193dc 100644 --- a/crates/januskey-cli/src/keys.rs +++ b/crates/januskey-cli/src/keys.rs @@ -63,8 +63,15 @@ const KEY_LENGTH: usize = 32; /// Key algorithm types #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum KeyAlgorithm { + /// AES-256-GCM symmetric key — the only algorithm actually implemented. Aes256Gcm, + /// Reserved / NOT IMPLEMENTED. No Ed25519 keypair is generated; key + /// generation for this variant is refused at the CLI. Retained so + /// historical serialized metadata/audit entries still deserialize. Ed25519, + /// Reserved / NOT IMPLEMENTED. No X25519 keypair is generated; key + /// generation for this variant is refused at the CLI. Retained so + /// historical serialized metadata/audit entries still deserialize. X25519, } diff --git a/crates/januskey-cli/src/keys_cli.rs b/crates/januskey-cli/src/keys_cli.rs index 073c980..a9197c6 100644 --- a/crates/januskey-cli/src/keys_cli.rs +++ b/crates/januskey-cli/src/keys_cli.rs @@ -279,15 +279,23 @@ fn cmd_generate( let algorithm = match key_type.to_lowercase().as_str() { "aes256" | "aes-256" | "aes256gcm" => KeyAlgorithm::Aes256Gcm, - "ed25519" => KeyAlgorithm::Ed25519, - "x25519" => KeyAlgorithm::X25519, - _ => { + // Ed25519/X25519 are NOT implemented: SecretKey::generate() only + // produces 32 random bytes and ignores the algorithm, so generating + // one would yield a random blob merely labelled "Ed25519"/"X25519", + // not a real keypair. Refuse rather than advertise a capability that + // does not exist. (Re-enable once dalek-backed signing/DH lands.) + "ed25519" | "x25519" => { return Err(format!( - "Unknown key type: {}. Use: aes256, ed25519, x25519", - key_type + "Key type '{}' is not implemented yet: JanusKey has no \ + asymmetric key generation (only AES-256-GCM symmetric keys). \ + Refusing to generate a random blob mislabelled as {}.", + key_type, key_type ) .into()) } + _ => { + return Err(format!("Unknown key type: {}. Use: aes256", key_type).into()) + } }; let key_purpose = match purpose.to_lowercase().as_str() { From 71a94560565e7c40289f0fa102af50064c8ea31e Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 01:36:39 +0000 Subject: [PATCH 3/4] fix(deps): clear cargo-audit advisories via root-cause bumps The `audit` CI job (cargo audit --deny warnings / --deny unmaintained) denied on two advisories, both pre-existing and unrelated to the crypto change on this branch. Resolve them at the source rather than ignoring: - Bump indicatif 0.17 -> 0.18: 0.18 drops the `number_prefix` dependency entirely, clearing RUSTSEC-2025-0119 (number_prefix unmaintained). Only ProgressBar + ProgressStyle::default_bar() are used here, stable across the bump; `cargo build -p januskey` is clean on 0.18.6. - Update anyhow 1.0.102 -> 1.0.103, the patched release for RUSTSEC-2026-0190 (unsound Error::downcast_mut). That API is not called anywhere in this codebase in any case. number_prefix is now absent from Cargo.lock; anyhow is 1.0.103. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_015qwVESTcbfanY2iJPQNoSz --- Cargo.lock | 48 +++++++++++++++++++++------------- crates/januskey-cli/Cargo.toml | 2 +- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 073449e..7fd451b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -119,9 +119,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "2a4385e2e34eb35d6b3efe798b9eb88096925d87726c0798709bf56d9ed84af3" [[package]] name = "argon2" @@ -366,6 +366,18 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "console" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" +dependencies = [ + "encode_unicode", + "libc", + "unicode-width", + "windows-sys 0.61.2", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -483,7 +495,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "658bce805d770f407bc62102fca7c2c64ceef2fbcb2b8bd19d2765ce093980de" dependencies = [ - "console", + "console 0.15.11", "shell-words", "tempfile", "thiserror", @@ -547,7 +559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -735,14 +747,14 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.11" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ - "console", - "number_prefix", + "console 0.16.4", "portable-atomic", "unicode-width", + "unit-prefix", "web-time", ] @@ -763,7 +775,7 @@ checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -901,12 +913,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - [[package]] name = "once_cell" version = "1.21.4" @@ -1245,7 +1251,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1386,7 +1392,7 @@ dependencies = [ "getrandom 0.4.3", "once_cell", "rustix", - "windows-sys 0.61.2", + "windows-sys 0.59.0", ] [[package]] @@ -1449,6 +1455,12 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + [[package]] name = "universal-hash" version = "0.5.1" @@ -1605,7 +1617,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.2", + "windows-sys 0.48.0", ] [[package]] diff --git a/crates/januskey-cli/Cargo.toml b/crates/januskey-cli/Cargo.toml index 80a3f50..49bbc2c 100644 --- a/crates/januskey-cli/Cargo.toml +++ b/crates/januskey-cli/Cargo.toml @@ -29,7 +29,7 @@ dirs = "5" walkdir = "2" colored = "2" dialoguer = "0.11" -indicatif = "0.17" +indicatif = "0.18" glob = "0.3" whoami = "1" From 27238db78dea47913408e193c85c40b5c779a52d Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Jul 2026 01:36:40 +0000 Subject: [PATCH 4/4] ci: fix pre-existing failures so PR checks can actually pass MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four CI checks failed on every PR (and on main) for reasons unrelated to any code change — the "CI that cannot pass" problem. Fix each: - rust-ci.yml: the job calls the shared reusable rust-ci-reusable.yml with no `with:` block, so its required `toolchain` input was empty and the "parse toolchain version" step failed with `'toolchain' is a required input`. Pass `toolchain: stable` (matches .tool-versions and the dtolnay/rust-toolchain pins in e2e.yml). - tests/aspect/cross_cutting_test.sh: the Documentation check asserted README.adoc, but the repo ships README.md (root .adoc is EXPLAINME.adoc). Accept either; aspect suite now PASS 29 / FAIL 0. - cargo-audit.yml create-issue: `needs: audit` + `if: failure()` ran on PR events where GITHUB_TOKEN is read-only, so `gh issue create` 403'd. Guard with `&& github.event_name != 'pull_request'`; issues are still filed on push/schedule runs. Both workflow files keep their SPDX line-1 header and top-level permissions block (workflow-linter.yml requirements); YAML validated. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_015qwVESTcbfanY2iJPQNoSz --- .github/workflows/cargo-audit.yml | 5 ++++- .github/workflows/rust-ci.yml | 2 ++ tests/aspect/cross_cutting_test.sh | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cargo-audit.yml b/.github/workflows/cargo-audit.yml index ac31a29..cf43d69 100644 --- a/.github/workflows/cargo-audit.yml +++ b/.github/workflows/cargo-audit.yml @@ -38,7 +38,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 15 needs: audit - if: failure() + # Only file a tracking issue on push/schedule runs. On pull_request events + # GITHUB_TOKEN is forced read-only, so `gh issue create` 403s; guarding here + # keeps PR runs green (the audit job itself still gates the PR). + if: failure() && github.event_name != 'pull_request' permissions: issues: write steps: diff --git a/.github/workflows/rust-ci.yml b/.github/workflows/rust-ci.yml index c60e60a..432adfb 100644 --- a/.github/workflows/rust-ci.yml +++ b/.github/workflows/rust-ci.yml @@ -15,3 +15,5 @@ permissions: jobs: rust-ci: uses: hyperpolymath/standards/.github/workflows/rust-ci-reusable.yml@d135b05bfc647d0c0fbfedc7e80f37ea50f49236 + with: + toolchain: stable diff --git a/tests/aspect/cross_cutting_test.sh b/tests/aspect/cross_cutting_test.sh index 4f57c53..37cd574 100755 --- a/tests/aspect/cross_cutting_test.sh +++ b/tests/aspect/cross_cutting_test.sh @@ -51,7 +51,7 @@ check "No unsafe in reversible-core" "! grep -rh 'unsafe' '${JK_DIR}/crates/reve # --- Documentation --- echo "--- Documentation ---" -check "README.adoc exists" "[ -f '${JK_DIR}/README.adoc' ]" +check "README exists" "[ -f '${JK_DIR}/README.md' ] || [ -f '${JK_DIR}/README.adoc' ]" check "SECURITY.md exists" "[ -f '${JK_DIR}/SECURITY.md' ]" check "ARCHITECTURE.md exists" "[ -f '${JK_DIR}/ARCHITECTURE.md' ]" check "PROOF-NEEDS.md exists" "[ -f '${JK_DIR}/PROOF-NEEDS.md' ]"