diff --git a/enforcing-invariants/Cargo.toml b/enforcing-invariants/Cargo.toml
new file mode 100644
index 0000000000000000000000000000000000000000..fb3dd3c6f71a70ef3b7eabcb4be75e585267b2a3
--- /dev/null
+++ b/enforcing-invariants/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "enforcing-invariants"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+rand = "0.9.0"
\ No newline at end of file
diff --git a/enforcing-invariants/src/main.rs b/enforcing-invariants/src/main.rs
new file mode 100644
index 0000000000000000000000000000000000000000..6e1d908fd5794f8357df2997aa9219bb0693930b
--- /dev/null
+++ b/enforcing-invariants/src/main.rs
@@ -0,0 +1,239 @@
+use std::{ptr, mem, collections::HashSet};
+
+use rand::{rngs::ThreadRng, Rng};
+
+/// A list of possible holders for an item.
+/// 
+/// # Invariants
+/// 
+/// The list of possible holders does not contain duplicates.
+pub struct PossibleHolders {
+    vec: Vec<usize>
+}
+impl PossibleHolders {
+    /// Returns a [`PossibleHolders`] containing the same items as `vec`.
+    /// 
+    /// If `vec` does not contain duplicates, a [`Some`] is returned
+    /// containing the corresponding [`PossibleHolders`];
+    /// otherwise, [`None`] is returned.
+    pub fn from_vec(vec: Vec<usize>) -> Option<PossibleHolders> {
+        let mut set = HashSet::new();
+        for item in vec.iter() {
+            if !set.insert(item) {
+                return None
+            }
+        }
+        Some(PossibleHolders { vec: vec })
+    }
+
+    /// Returns a reference to the list of possible holders.
+    pub fn holders(&self) -> &Vec<usize> {
+        &self.vec
+    }
+
+    /// Swaps the first item in the list with the item with index `idx`.
+    /// 
+    /// # Safety
+    /// 
+    /// Calling this function when `idx` is `0usize` or when `idx` is not
+    /// an index of the list is undefined behavior.
+    pub unsafe fn swap_first_unchecked(&mut self, idx: usize) -> usize {
+        // SAFETY: 0 < idx < self.vec.len() so fst and snd are non-overlapping.
+        // Furthermore, self is valid for writes until return,
+        // and self is not accessed again.
+        let (fst, snd) = unsafe {
+            let fst = ptr::from_mut(self.vec.get_unchecked_mut(0));
+            let snd = ptr::from_mut(self.vec.get_unchecked_mut(idx));
+            (&mut *fst, &mut *snd)
+        };
+        mem::swap(fst, snd);
+        *fst
+    }
+}
+
+/// A [`String`] value together with a list of possible holders.
+/// 
+/// # Invariants
+/// 
+/// The list of possible holders satisfies the invariants of [`PossibleHolders`],
+/// and is guaranteed to have length at least 2.
+pub struct ItemWithHolders {
+    value: String,
+    holders: PossibleHolders
+}
+impl ItemWithHolders {
+    /// Returns a [`ItemWithHolders`] with possible holders `holders`
+    /// and value `value`.
+    /// 
+    /// If `holders` is of length at least 2, a [`Some`] is returned
+    /// containing the corresponding [`ItemWithHolders`];
+    /// otherwise, [`None`] is returned.
+    pub fn new(value: String, holders: PossibleHolders) -> Option<ItemWithHolders> {
+        if holders.holders().len() >= 2 {
+            Some(ItemWithHolders {
+                value: value,
+                holders: holders
+            })
+        } else {
+            None
+        }
+    }
+
+    /// Returns the first possible holder in the list of `self`.
+    pub fn get_first(&self) -> usize {
+        // SAFETY: the list of possible holders for `self` is of length
+        // at least 2.
+        unsafe { *self.holders.holders().get_unchecked(0) }
+    }
+
+    /// Swaps the first possible holder in `self` by a randomly selected
+    /// possible holder among the rest in its list.
+    pub fn change_first(&mut self, rng: &mut ThreadRng) -> usize {
+        let idx = rng.random_range(1 .. self.holders.holders().len());
+        // SAFETY: 0 < 1 <= idx < self.holders.holders().len()
+        unsafe { self.holders.swap_first_unchecked(idx) }
+    }
+
+    /// Returns a reference to the value in `self`.
+    pub fn value(&self) -> &String {
+        &self.value
+    }
+
+    /// Returns a reference to the holders list in `self`.
+    pub fn holders(&self) -> &PossibleHolders {
+        &self.holders
+    }
+
+    /// Returns the maximum holder in the list of `self`.
+    pub fn max_holder(&self) -> usize {
+        let maxopt = self.holders.holders().iter().max();
+        // SAFETY: the list of possible holders for `self` is nonempty.
+        unsafe { *maxopt.unwrap_unchecked() }
+    }
+}
+
+/// A [`ItemWithHolders`] where the first item is understood as its current
+/// holder.
+pub struct HeldItem {
+    item: ItemWithHolders
+}
+impl HeldItem {
+    /// Returns a pair `(held, holder)`, where `held` is `item` as a [`HeldItem`]
+    /// and `holder` is the first holder in its holders list.
+    pub fn new(item: ItemWithHolders) -> (HeldItem, usize) {
+        (HeldItem { item: item }, 0usize)
+    }
+
+    /// Returns a reference to the value in `self`.
+    pub fn get_value(&self) -> &String {
+        self.item.value()
+    }
+
+    /// Returns a reference to the holders list in `self`.
+    pub fn get_possible_holders(&self) -> &Vec<usize> {
+        self.item.holders().holders()
+    }
+
+    /// Returns the holder that currently holds `self`.
+    pub fn get_holder(&self) -> usize {
+        self.item.get_first()
+    }
+
+    /// Chooses a different holder for `self` among those in its holders list.
+    pub fn choose_another_holder(&mut self, rng: &mut ThreadRng) -> usize {
+        self.item.change_first(rng)
+    }
+}
+
+/// A list of holders, each holding a list of items.
+pub struct HolderFamily {
+    vec: Vec<Vec<HeldItem>>
+}
+impl HolderFamily {
+    /// Creates a new empty list of holders.
+    pub fn new() -> HolderFamily {
+        HolderFamily {
+            vec: Vec::new()
+        }
+    }
+
+    /// Returns a reference to the list of holders.
+    pub fn lists(&self) -> &Vec<Vec<HeldItem>> {
+        &self.vec
+    }
+
+    /// Adds an [`ItemWithHolders`] `item` to `self` in the list corresponding
+    /// to the current holder of `item`.
+    /// 
+    /// If the underlying list of holders does not contain the current holder,
+    /// it is extended with new holders to fit it. All other new holders hold nothing.
+    pub fn add_item(&mut self, item: ItemWithHolders) {
+        let needed = item.max_holder().checked_add(1usize)
+            .expect("capacity exceeded");
+        if needed >= self.vec.len() {
+            self.vec.resize_with(needed, || Vec::new())
+        }
+        let (held, holder) = HeldItem::new(item);
+        // SAFETY: above we make sure this is within bounds.
+        let list = unsafe { self.vec.get_unchecked_mut(holder) };
+        list.push(held)
+    }
+
+    /// Redistributes every item in `holder`'s list in `self` to a randomly selected
+    /// new holder. The holder is selected among the rest of each item's possible holders.
+    pub fn redistribute_items(&mut self, holder: usize, rng: &mut ThreadRng) {
+        if holder < self.vec.len() {
+            let lists = self.vec.as_mut_ptr();
+            // SAFETY: lists + holder is within the same allocation,
+            // and ptr is valid for writes.
+            let holder_list = unsafe {
+                let ptr = lists.add(holder);
+                &mut *ptr
+            };
+            for mut item in holder_list.drain(..) {
+                let dest = item.choose_another_holder(rng);
+                // SAFETY: lists + dest is within the same allocation.
+                // Moreover, `dest` is guaranteed to be distinct from `holder`,
+                // so dest_list is valid for writes.
+                let dest_list = unsafe { &mut *lists.add(dest) };
+                dest_list.push(item)
+            }
+        }
+    }
+}
+
+
+fn main() {
+    let mut rng = rand::rng();
+    let mut family = HolderFamily::new();
+
+    let mut count = 0;
+    while count < 50 {
+        let opt_holders = {
+            let mut vec = Vec::new();
+            for _ in 0 .. 4 {
+                vec.push(rng.random_range(0 .. 16));
+            }
+            PossibleHolders::from_vec(vec)
+        };
+        if let Some(holders) = opt_holders {
+            let value = format!("Item #{}", count);
+            let item = ItemWithHolders::new(value, holders).unwrap();
+            family.add_item(item)
+        }
+        count += 1;
+    }
+    for _ in 0 .. 1000 {
+        let holder = rng.random_range(0 .. 16);
+        family.redistribute_items(holder, &mut rng);
+    }
+    for (n, list) in family.lists().iter().enumerate() {
+        println!("Holder #{}", n);
+        for item in list {
+            assert!(item.get_holder() == n);
+            println!("\t{}, holders: {:?}",
+                item.get_value(),
+                item.get_possible_holders())
+        }
+    }
+}
diff --git a/unsafe-rust/presentation.tex b/unsafe-rust/presentation.tex
index 0e7f8dabb881ddd3e4cdc5aaed34712233ecab72..bfc39c02f6e7d8157a5bca2b430df4b7c143d3e7 100644
--- a/unsafe-rust/presentation.tex
+++ b/unsafe-rust/presentation.tex
@@ -21,6 +21,7 @@ Safe Rust guarantees{${}^{\text{[\emph{citation needed}]}}$} memory safety:
     \item Calls respect the corresponding ABI
 \end{itemize}
 
+\pause
 Safe Rust does not guarantee (in principle):
 \begin{itemize}
     \item General race conditions (deadlocks, out-of-spec synchronization)
@@ -29,6 +30,7 @@ Safe Rust does not guarantee (in principle):
     \item Panics and aborts
 \end{itemize}
 
+\pause
 The safe/unsafe boundary can be weaponized though!
 \end{frame}
 
@@ -84,7 +86,10 @@ Raw pointers need not respect the borrow rules...
         \item \emph{The Jedi version:} Using unsafe even once means you are foregoing all safety guarantees
         \item \emph{The Sith version:} If you use unsafe, you may as well use it everywhere
     \end{itemize}
-
+    \pause
     \emph{Reality (the Andor version)}: Safe does not mean ``memory-safe'', it means ``unsafety correctly encapsulated by the API''.
+
+    \pause
+    \emph{The Rael version}: Same as Andor, but also ``memory safety can be strengthened to whatever you feel like''.
 \end{frame}
 \end{document}
\ No newline at end of file