Skip to main content

qualia_core_db/foundation/
crdt.rs

1use crate::NQuin;
2use serde::{Deserialize, Serialize};
3
4/// Represents a cryptographic grant of authority from a Principal to a Delegate.
5/// Essential for Guardianship (e.g., homeless individual granting read access to a social worker).
6///
7/// Zero-heap (AGENTS.md §4-F): the DIDs are carried as their 32-byte identifier hashes
8/// (q_hash-style handles, not the textual DID) and the proof is the raw 64-byte Ed25519
9/// signature — no `String` allocation, so a grant can be created/validated on a hot path
10/// (e.g. per-quin Bilateral Micro-Commons checks). Callers hash the DID before constructing.
11#[derive(Serialize, Deserialize, Debug, Clone)]
12pub struct DelegatedAccess {
13    /// 32-byte hash of the principal's (grantor's) DID.
14    #[serde(with = "serde_bytes")]
15    pub principal_did: [u8; 32],
16    /// 32-byte hash of the delegate's (grantee's) DID.
17    #[serde(with = "serde_bytes")]
18    pub delegate_did: [u8; 32],
19    pub context_bound: u64, // The specific semantic context they are allowed to access (0 = global)
20    pub expiration_timestamp: u64,
21    /// Raw 64-byte Ed25519 signature over the grant.
22    #[serde(with = "serde_bytes")]
23    pub cryptographic_proof: [u8; 64],
24}
25
26/// Last-Write-Wins (LWW) CRDT Resolver
27/// Ensures offline-first mobile devices can sync disparate state without conflicts.
28pub struct CrdtResolver;
29
30impl CrdtResolver {
31    /// Merges two conflicting mutations from the same logical Context graph.
32    /// Returns the mathematically deterministically "winning" Quin.
33    pub fn resolve_lww(local: &NQuin, remote: &NQuin, is_selfhood_domain: bool) -> NQuin {
34        if is_selfhood_domain {
35            return local.clone(); // Bifurcated CRDT Logic: Protect the unalienable selfhood record from automated external merging.
36        }
37
38        let local_clock = local.extract_lamport_clock();
39        let remote_clock = remote.extract_lamport_clock();
40
41        if remote_clock > local_clock {
42            remote.clone()
43        } else if local_clock > remote_clock {
44            local.clone()
45        } else {
46            // Clocks are identical (concurrent mutation).
47            // Tie-break deterministically using the mathematical values of the nodes.
48            // A simple hash tie-breaker or magnitude check works for CRDTs.
49            if remote.object > local.object {
50                remote.clone()
51            } else {
52                local.clone()
53            }
54        }
55    }
56
57    /// Validates a Role-Based Delegation.
58    /// Ensures that a delegate (e.g., social worker) has cryptographic authority
59    /// to mutate or read the principal's (e.g., homeless individual) state.
60    pub fn verify_delegation(
61        access: &DelegatedAccess,
62        target_context: u64,
63        current_timestamp: u64,
64    ) -> bool {
65        if access.expiration_timestamp < current_timestamp {
66            return false; // Expired
67        }
68        if access.context_bound != target_context && access.context_bound != 0 {
69            return false; // Out of bounds
70        }
71
72        // In production, we verify `cryptographic_proof` against `principal_did` public key.
73        true
74    }
75}
76
77#[cfg(test)]
78mod tests {
79    use super::*;
80
81    #[test]
82    fn qualia_crdt_resolution() {
83        let mut q_local = NQuin {
84            subject: 1,
85            predicate: 2,
86            object: 100,
87            context: 5,
88            metadata: 0,
89            parity: 0,
90        };
91        q_local.set_lamport_clock(5);
92
93        let mut q_remote = NQuin {
94            subject: 1,
95            predicate: 2,
96            object: 200,
97            context: 5,
98            metadata: 0,
99            parity: 0,
100        };
101        q_remote.set_lamport_clock(8); // Remote occurred later
102
103        // Remote wins due to clock
104        let winner_clock = CrdtResolver::resolve_lww(&q_local, &q_remote, false);
105        assert_eq!(
106            winner_clock.object, 200,
107            "CRDT failed to resolve higher lamport clock"
108        );
109
110        // Concurrent mutations (same clock)
111        let mut q_concurrent = NQuin {
112            subject: 1,
113            predicate: 2,
114            object: 50,
115            context: 5,
116            metadata: 0,
117            parity: 0,
118        };
119        q_concurrent.set_lamport_clock(5);
120
121        // Tie-breaker falls to magnitude
122        let winner_tie = CrdtResolver::resolve_lww(&q_local, &q_concurrent, false);
123        assert_eq!(
124            winner_tie.object, 100,
125            "CRDT failed deterministic tie-breaker"
126        );
127    }
128
129    #[test]
130    fn test_crdt_bifurcation() {
131        let mut q_local = NQuin {
132            subject: 1,
133            predicate: 2,
134            object: 100,
135            context: 5,
136            metadata: 0,
137            parity: 0,
138        };
139        q_local.set_lamport_clock(5);
140
141        let mut q_remote = NQuin {
142            subject: 1,
143            predicate: 2,
144            object: 200,
145            context: 5,
146            metadata: 0,
147            parity: 0,
148        };
149        q_remote.set_lamport_clock(8); // Remote occurred later
150
151        // Normal sync (qp:Project Commons)
152        let winner_commons = CrdtResolver::resolve_lww(&q_local, &q_remote, false);
153        assert_eq!(
154            winner_commons.object, 200,
155            "CRDT failed to resolve higher lamport clock in Commons"
156        );
157
158        // Selfhood sync (wf: WellFair)
159        let winner_selfhood = CrdtResolver::resolve_lww(&q_local, &q_remote, true);
160        assert_eq!(
161            winner_selfhood.object, 100,
162            "CRDT failed to protect selfhood domain from external merge"
163        );
164    }
165}
166
167/// A zero-allocation suspended transaction context.
168/// Holds the flattened Webizen VM execution frame while waiting for network consensus.
169#[derive(Clone, Copy)]
170pub struct SuspendedTransaction {
171    pub agreement_id: u64,
172    pub threshold: u8,
173    pub collected_signatures: u8,
174    pub registers: [Option<u64>; 16],
175    pub bytecode_buffer: [Option<crate::modalities::logic::core::WebizenOpcode>; 64],
176    pub yielded_op: Option<crate::modalities::logic::core::WebizenOpcode>,
177    pub suspended_quin: NQuin,
178}
179
180/// A fixed-size pending queue for Webizen VM transactions waiting on M:N Guardianship signatures.
181pub struct SuspendedTransactionQueue {
182    pub queue: [Option<SuspendedTransaction>; 32],
183}
184
185impl SuspendedTransactionQueue {
186    pub const fn new() -> Self {
187        // Explicitly initialize the fixed array without vectors
188        Self { queue: [None; 32] }
189    }
190
191    /// Pushes a flattened execution frame to the pending queue.
192    pub fn push(&mut self, transaction: SuspendedTransaction) -> Result<(), &'static str> {
193        for slot in self.queue.iter_mut() {
194            if slot.is_none() {
195                *slot = Some(transaction);
196                return Ok(());
197            }
198        }
199        Err("SuspendedTransactionQueue is full!")
200    }
201
202    /// Asynchronously wakes up a suspended transaction if the signature threshold is met by an incoming WebRTC token.
203    pub fn apply_consensus_token(&mut self, token_quin: &NQuin) -> Option<SuspendedTransaction> {
204        for slot in self.queue.iter_mut() {
205            if let Some(tx) = slot {
206                if tx.agreement_id == token_quin.context {
207                    tx.collected_signatures += 1;
208                    if tx.collected_signatures >= tx.threshold {
209                        return slot.take(); // Pop from queue and return for immediate Webizen resumption
210                    }
211                }
212            }
213        }
214        None
215    }
216}