diff --git a/cubesys/src/commands.rs b/cubesys/src/commands.rs
index 13c78dd..27bbc91 100644
--- a/cubesys/src/commands.rs
+++ b/cubesys/src/commands.rs
@@ -1184,7 +1184,20 @@ impl Session {
let dir = it.next().ok_or_else(|| "ls needs
".to_string())?;
// R5: directory reads are metadata reads — honor the read gate
// so an attacker can't enumerate a victim's records by name.
- let dir_coord = crate::path_to_czyx(dir).map_err(|e| e.to_string())?;
+ // Use parse_path (not path_to_czyx) because ls targets a
+ // directory prefix, which path_to_czyx rejects as "not a record".
+ let parsed = cubefs::path::parse_path(dir)
+ .map_err(|e| format!("ls: bad path {dir}: {e}"))?;
+ // The ACL gate wants the directory's prefix coordinate
+ // (trailing axes zeroed) — same key the NullSpace acl_bucket
+ // uses for directory ACLs.
+ let dir_coord = match parsed.axes.len() {
+ 0 => Czyx::new(0, 0, 0, 0), // root
+ 1 => Czyx::new(parsed.axes[0], 0, 0, 0),
+ 2 => Czyx::new(parsed.axes[0], parsed.axes[1], 0, 0),
+ 3 => Czyx::new(parsed.axes[0], parsed.axes[1], parsed.axes[2], 0),
+ _ => return Err("ls: path too deep".to_string()),
+ };
if let Some(msg) = self.admit_read(dir_coord) {
self.audit_now(OP_READ, dir_coord, false);
return Err(msg);
diff --git a/cubetrace/src/lib.rs b/cubetrace/src/lib.rs
index a915faf..136009e 100644
--- a/cubetrace/src/lib.rs
+++ b/cubetrace/src/lib.rs
@@ -19,7 +19,7 @@
//! * `replay_all` deterministically replays the stored stream in timestamp
//! order (§977/§1118: "deterministic replay first").
-use cubecode::{Behavior, CodeCell, Kind};
+use cubecode::{Behavior, Kind};
use cubecoords::{CubeHeader, Czyx};
use cubestore::{CubeBackend, CubeStore, HashBackend};
@@ -169,7 +169,7 @@ impl Tracer {
/// Store one event under a fresh CZYX coordinate in the `c240` band.
pub fn store_event(&mut self, ev: &TraceEvent) -> Czyx {
- let label = Czyx::new(C_TRACE, 1, (ev.kind as u8), self.next_x);
+ let label = Czyx::new(C_TRACE, 1, ev.kind as u8, self.next_x);
self.next_x = self.next_x.wrapping_add(1).max(1);
let mut h = CubeHeader::new();
h.title = Some(format!("{:?}:{:?}", ev.kind, ev.coord));
@@ -220,13 +220,17 @@ mod tests {
}
}
+ fn behavior(flag: u16) -> Behavior {
+ Behavior(flag)
+ }
+
#[test]
fn event_round_trips_through_bytes() {
let e = ev(
EventKind::Syscall,
42,
Czyx::new(1, 2, 3, 4),
- Behavior::HOT_PATH,
+ behavior(Behavior::HOT_PATH),
);
let back = TraceEvent::from_bytes(&e.to_bytes()).expect("decodes");
assert_eq!(e, back);
@@ -239,13 +243,13 @@ mod tests {
EventKind::BasicBlock,
10,
Czyx::new(1, 0, 0, 1),
- Behavior::PURE,
+ behavior(Behavior::PURE),
),
ev(
EventKind::Syscall,
20,
Czyx::new(1, 0, 0, 2),
- Behavior::IO_HEAVY,
+ behavior(Behavior::IO_HEAVY),
),
ev(
EventKind::Meta,
@@ -273,13 +277,13 @@ mod tests {
EventKind::BasicBlock,
30,
Czyx::new(1, 0, 0, 1),
- Behavior::PURE,
+ behavior(Behavior::PURE),
),
ev(
EventKind::Syscall,
10,
Czyx::new(1, 0, 0, 2),
- Behavior::IO_HEAVY,
+ behavior(Behavior::IO_HEAVY),
),
ev(
EventKind::Meta,