diff options
| author | mo khan <mo@mokhan.ca> | 2025-07-15 16:37:08 -0600 |
|---|---|---|
| committer | mo khan <mo@mokhan.ca> | 2025-07-17 16:30:22 -0600 |
| commit | 45df4d0d9b577fecee798d672695fe24ff57fb1b (patch) | |
| tree | 1b99bf645035b58e0d6db08c7a83521f41f7a75b /vendor/logos-codegen/src/graph/fork.rs | |
| parent | f94f79608393d4ab127db63cc41668445ef6b243 (diff) | |
feat: migrate from Cedar to SpiceDB authorization system
This is a major architectural change that replaces the Cedar policy-based
authorization system with SpiceDB's relation-based authorization.
Key changes:
- Migrate from Rust to Go implementation
- Replace Cedar policies with SpiceDB schema and relationships
- Switch from envoy `ext_authz` with Cedar to SpiceDB permission checks
- Update build system and dependencies for Go ecosystem
- Maintain Envoy integration for external authorization
This change enables more flexible permission modeling through SpiceDB's
Google Zanzibar inspired relation-based system, supporting complex
hierarchical permissions that were difficult to express in Cedar.
Breaking change: Existing Cedar policies and Rust-based configuration
will no longer work and need to be migrated to SpiceDB schema.
Diffstat (limited to 'vendor/logos-codegen/src/graph/fork.rs')
| -rw-r--r-- | vendor/logos-codegen/src/graph/fork.rs | 267 |
1 files changed, 0 insertions, 267 deletions
diff --git a/vendor/logos-codegen/src/graph/fork.rs b/vendor/logos-codegen/src/graph/fork.rs deleted file mode 100644 index 6b59836b..00000000 --- a/vendor/logos-codegen/src/graph/fork.rs +++ /dev/null @@ -1,267 +0,0 @@ -use crate::graph::{Disambiguate, Graph, NodeId, Range}; - -#[derive(Clone)] -pub struct Fork { - /// LUT matching byte -> node id - lut: Box<[Option<NodeId>; 256]>, - /// State to go to if no arms are matching - pub miss: Option<NodeId>, -} - -impl Fork { - pub fn new() -> Self { - Fork { - lut: Box::new([None; 256]), - miss: None, - } - } - - pub fn miss<M>(mut self, miss: M) -> Self - where - M: Into<Option<NodeId>>, - { - self.miss = miss.into(); - self - } - - pub fn add_branch<R, T>(&mut self, range: R, then: NodeId, graph: &mut Graph<T>) - where - R: Into<Range>, - T: Disambiguate, - { - for byte in range.into() { - match &mut self.lut[byte as usize] { - Some(other) if *other != then => { - *other = graph.merge(*other, then); - } - opt => *opt = Some(then), - } - } - } - - // TODO: Add result with a printable error - pub fn merge<T>(&mut self, other: Fork, graph: &mut Graph<T>) - where - T: Disambiguate, - { - self.miss = match (self.miss, other.miss) { - (None, None) => None, - (Some(id), None) | (None, Some(id)) => Some(id), - (Some(a), Some(b)) => Some(graph.merge(a, b)), - }; - - for (left, right) in self.lut.iter_mut().zip(other.lut.iter()) { - *left = match (*left, *right) { - (None, None) => continue, - (Some(id), None) | (None, Some(id)) => Some(id), - (Some(a), Some(b)) => Some(graph.merge(a, b)), - } - } - } - - pub fn branches(&self) -> ForkIter<'_> { - ForkIter { - offset: 0, - lut: &self.lut, - } - } - - /// Checks if all bytes in the `range` have a branch on this - /// fork, and those branches are resolve to the same `NodeId`. - pub fn contains<R>(&self, range: R) -> Option<NodeId> - where - R: Into<Range>, - { - let mut range = range.into(); - let byte = range.next()?; - let first = self.lut[byte as usize]?; - - for byte in range { - if first != self.lut[byte as usize]? { - return None; - } - } - - Some(first) - } - - pub fn branch<R>(mut self, range: R, then: NodeId) -> Self - where - R: Into<Range>, - { - for byte in range.into() { - match &mut self.lut[byte as usize] { - Some(other) if *other != then => { - panic!("Overlapping branches"); - } - opt => *opt = Some(then), - } - } - self - } - - pub fn shake<T>(&self, graph: &Graph<T>, filter: &mut [bool]) { - if let Some(id) = self.miss { - if !filter[id.get()] { - filter[id.get()] = true; - graph[id].shake(graph, filter); - } - } - - for (_, id) in self.branches() { - if !filter[id.get()] { - filter[id.get()] = true; - graph[id].shake(graph, filter); - } - } - } -} - -pub struct ForkIter<'a> { - offset: usize, - lut: &'a [Option<NodeId>; 256], -} - -impl Iterator for ForkIter<'_> { - type Item = (Range, NodeId); - - fn next(&mut self) -> Option<Self::Item> { - // Consume empty slots - self.offset += self.lut[self.offset..] - .iter() - .take_while(|next| next.is_none()) - .count(); - - let then = self.lut.get(self.offset).copied().flatten()?; - let start = self.offset; - - // Consume all slots with same NodeId target - self.offset += self.lut[self.offset..] - .iter() - .take_while(|next| **next == Some(then)) - .count(); - - Some(( - Range { - start: start as u8, - end: (self.offset - 1) as u8, - }, - then, - )) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::graph::Node; - use pretty_assertions::assert_eq; - - #[test] - fn fork_iter() { - let mut buf = [None; 256]; - - for byte in b'4'..=b'7' { - buf[byte as usize] = Some(NodeId::new(1)); - } - for byte in b'a'..=b'd' { - buf[byte as usize] = Some(NodeId::new(2)); - } - - let iter = ForkIter { - offset: 0, - lut: &buf, - }; - - assert_eq!( - &[ - ( - Range { - start: b'4', - end: b'7' - }, - NodeId::new(1) - ), - ( - Range { - start: b'a', - end: b'd' - }, - NodeId::new(2) - ), - ], - &*iter.collect::<Vec<_>>(), - ); - } - - #[test] - fn merge_no_conflict() { - let mut graph = Graph::new(); - - let leaf1 = graph.push(Node::Leaf("FOO")); - let leaf2 = graph.push(Node::Leaf("BAR")); - - let mut fork = Fork::new().branch(b'1', leaf1); - - fork.merge(Fork::new().branch(b'2', leaf2), &mut graph); - - assert_eq!(fork, Fork::new().branch(b'1', leaf1).branch(b'2', leaf2)); - } - - #[test] - fn merge_miss_right() { - let mut graph = Graph::new(); - - let leaf1 = graph.push(Node::Leaf("FOO")); - let leaf2 = graph.push(Node::Leaf("BAR")); - - let mut fork = Fork::new().branch(b'1', leaf1); - - fork.merge(Fork::new().miss(leaf2), &mut graph); - - assert_eq!(fork, Fork::new().branch(b'1', leaf1).miss(leaf2)); - } - - #[test] - fn merge_miss_left() { - let mut graph = Graph::new(); - - let leaf1 = graph.push(Node::Leaf("FOO")); - let leaf2 = graph.push(Node::Leaf("BAR")); - - let mut fork = Fork::new().miss(leaf1); - - fork.merge(Fork::new().branch(b'2', leaf2), &mut graph); - - assert_eq!(fork, Fork::new().branch(b'2', leaf2).miss(leaf1)); - } - - #[test] - fn contains_byte() { - let fork = Fork::new().branch('a'..='z', NodeId::new(42)); - - assert_eq!(fork.contains(b't'), Some(NodeId::new(42))); - } - - #[test] - fn contains_range() { - let fork = Fork::new() - .branch('a'..='m', NodeId::new(42)) - .branch('n'..='z', NodeId::new(42)); - - assert_eq!(fork.contains('i'..='r'), Some(NodeId::new(42))); - assert_eq!(fork.contains('a'..='z'), Some(NodeId::new(42))); - } - - #[test] - fn contains_different_ranges() { - let fork = Fork::new() - .branch('a'..='m', NodeId::new(42)) - .branch('n'..='z', NodeId::new(47)); - - assert_eq!(fork.contains('i'..='r'), None); - assert_eq!(fork.contains('a'..='z'), None); - assert_eq!(fork.contains('d'..='f'), Some(NodeId::new(42))); - assert_eq!(fork.contains('n'..='p'), Some(NodeId::new(47))); - } -} |
