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
13 changes: 10 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ permissions:

on:
push:
branches: [ main, master, fix/ci-hardening ]
branches: [ main, master ]
tags: [ 'v*' ]
pull_request:
branches: [ main, master, fix/ci-hardening ]
branches: [ main, master ]

jobs:
test:
Expand Down Expand Up @@ -103,7 +103,7 @@ jobs:

build-release:
needs: [test, lint]
if: startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/fix/ci-hardening'
if: startsWith(github.ref, 'refs/tags/v')
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
Expand Down Expand Up @@ -173,7 +173,14 @@ jobs:

go build -o "$BINARY_NAME" ./cmd/attest

- name: Upload artifacts
uses: actions/upload-artifact@v4
with:
name: attest-${{ matrix.os }}-${{ matrix.arch }}
path: attest-*

- name: Create release
if: startsWith(github.ref, 'refs/tags/v')
uses: softprops/action-gh-release@v1
with:
files: attest-*
Expand Down
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,35 @@
All notable changes to Attest are documented in this file.
The project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v0.3.0] - 2026-03-08

### Added

- **🤝 Capsule V1 Alignment**: Updated capsule root calculation to use JCS-based composite hashing.
- **🏗️ VEP Refactor**: Refactored the internal segment structure to promote Witness and Signature data to top-level pillars.
- **⚡ Noise State Machine**: Implemented Noise_XX handshake for authenticated session establishment.
- **⚓ TPM Key Binding**: Linked session security states to hardware-sealed identities.
- **🕵️ Debug Support**: Added optional encryption toggle for VEP construction during parity testing.
- **🐧 WSL Support**: Added platform-specific stub for TPM interfaces in virtual environments.


## [v0.2.0] - 2026-03-07

### Added
- **TPM Integrity Layer**: Added checksum verification to hardware-sealed identities to prevent data corruption.
- **Hardware Resilience**: Verified driver stability under concurrent load and improved recovery for lost keys.
- **Improved Error Messaging**: Mapped system-level hardware codes to descriptive messages.
- **Policy Utility**: Implemented `attest policy check` for manual verification of command strings.
- **Automation Support**: Added `--passphrase` flag for non-interactive certificate and agent creation.

### Fixed
- **Persistence**: Fixed an issue where guardrail settings were not saved between sessions.
- **Database Schema**: Implemented automated migrations for consistent schema updates.
- **Display**: Corrected Intent ID truncation in CLI list views.
- **Backup Logic**: Improved automated backup handling for directory-level operations.
- **Go/Rust Bridge**: Resolved protocol issues related to RSA padding and buffer lengths.


## [v0.1.0] - 2026-03-05

### ⚓ The Silicon-Rooted Release
Expand Down
7 changes: 6 additions & 1 deletion attest-rs/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ rpassword = "7.0"
reqwest = { version = "0.11", features = ["json"] }

# Storage (Ecosystem Aligned)
sqlx = { version = "0.7", features = ["runtime-tokio", "sqlite", "chrono", "uuid"] }
sqlx = { version = "0.8.6", features = ["runtime-tokio", "sqlite", "chrono", "uuid"] }
# Cryptography & Tunneling
snow = "0.9"
serde_jcs = "0.1"
ring = "0.17"

# Environmental Monitoring
notify = "6"
Expand All @@ -58,6 +62,7 @@ p3-field = "0.4.2"
p3-matrix = "0.4.2"
p3-goldilocks = "0.4.2"
p3-poseidon = "0.4.2"
p3-poseidon2 = "0.4.2"
p3-merkle-tree = "0.4.2"
p3-fri = "0.4.2"
p3-challenger = "0.4.2"
Expand Down
Binary file removed attest-rs/output.txt
Binary file not shown.
145 changes: 0 additions & 145 deletions attest-rs/output_utf8.txt

This file was deleted.

70 changes: 69 additions & 1 deletion attest-rs/src/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#![allow(clippy::not_unsafe_ptr_arg_deref)]

use crate::id::AttestAgent;
use std::ffi::CString;
use crate::runtime::policy::PolicyEngine;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;

use crate::tpm::create_identity_provider;
Expand Down Expand Up @@ -133,3 +134,70 @@ pub extern "C" fn attest_free_buffer(ptr: *mut u8, len: usize) {
}
}
}

#[no_mangle]
pub extern "C" fn attest_policy_engine_new() -> *mut PolicyEngine {
let engine = PolicyEngine::new();
Box::into_raw(Box::new(engine))
}

#[no_mangle]
pub extern "C" fn attest_policy_engine_free(ptr: *mut PolicyEngine) {
if !ptr.is_null() {
unsafe {
let _ = Box::from_raw(ptr);
}
}
}

#[no_mangle]
pub extern "C" fn attest_policy_engine_load_defaults(ptr: *mut PolicyEngine) {
let engine = unsafe {
assert!(!ptr.is_null());
&mut *ptr
};
engine.load_defaults();
}

#[no_mangle]
pub extern "C" fn attest_verify_intent(
agent_ptr: *mut AttestAgent,
policy_ptr: *mut PolicyEngine,
intent_json: *const c_char,
) -> bool {
let result = std::panic::catch_unwind(|| {
let _agent = unsafe {
assert!(!agent_ptr.is_null());
&*agent_ptr
};
let policy = unsafe {
assert!(!policy_ptr.is_null());
&*policy_ptr
};
let c_str = unsafe {
assert!(!intent_json.is_null());
CStr::from_ptr(intent_json)
};
let intent_str = c_str.to_str().unwrap();
let intent: crate::runtime::intent::Intent = serde_json::from_str(intent_str).unwrap();

let ctx = crate::runtime::policy::ActionContext {
action_type: "intent".into(),
target: intent.goal.clone(),
agent_id: _agent.id.clone(),
intent_id: intent.id.clone(),
..Default::default()
};

let (allowed, _) = policy.should_allow(&ctx);
allowed
});

match result {
Ok(allowed) => allowed,
Err(_) => {
eprintln!("[FFI] attest_verify_intent PANICKED");
false
}
}
}
3 changes: 2 additions & 1 deletion attest-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ pub use id::AttestAgent;
pub use keystore::KeyManager;
pub use persist::audit::{ActorType, AuditEvent, AuditEventType, AuditStore};
pub use persist::sqlite::LocalStore;
pub use runtime::intent::{Intent, IntentStatus};
pub use runtime::interceptor::AttestTerminalInterceptor;
pub use runtime::policy::{Policy, PolicyEngine};
pub use runtime::policy::{ActionContext, Policy, PolicyEngine};
pub use runtime::watcher::AttestWatcher;

pub mod config;
12 changes: 5 additions & 7 deletions attest-rs/src/persist/audit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,24 +125,22 @@ impl AuditStore {

self.local.save_event(&event).await?;

// 3. Generate ZK Proof (Phase 2)
// 3. Generate ZK Proof
let prev_root = last_hash
.as_ref()
.map(|h| {
let mut arr = [0u8; 32];
let decoded = hex::decode(h).unwrap_or_default();
if decoded.len() >= 32 {
arr.copy_from_slice(&decoded[..32]);
}
let len = decoded.len().min(32);
arr[..len].copy_from_slice(&decoded[..len]);
arr
})
.unwrap_or([0u8; 32]);

let event_hash_bytes = hex::decode(&event.hash).unwrap_or_default();
let mut event_hash = [0u8; 32];
if event_hash_bytes.len() >= 32 {
event_hash.copy_from_slice(&event_hash_bytes[..32]);
}
let hash_len = event_hash_bytes.len().min(32);
event_hash[..hash_len].copy_from_slice(&event_hash_bytes[..hash_len]);

if let Ok(proof) = crate::zk::AuditProver::prove_transition(prev_root, event_hash) {
let mut updated_event = event.clone();
Expand Down
Loading