Major Changes:
- Moved Rhai support from rhai_support/ to rhai/ module
- Implemented context-based execution with signatory access control
- Added TypeRegistry for dynamic type registration and object creation
- Refactored engine to use context (Vec<String>) instead of instance
- Removed old runner binary (moved to runner_rust crate)
Rhai Module:
- engine.rs: Core Rhai engine with context-based get_context()
- functions.rs: Rhai function bindings (create_note, create_event, etc.)
- mod.rs: Module exports and organization
Store Improvements:
- TypeRegistry for registering object types and creators
- Generic store uses type registry for dynamic object creation
- Improved error handling and type safety
Documentation:
- RHAI_REFACTOR_COMPLETE.md: Refactoring details
- SIGNATORY_ACCESS_CONTROL.md: Context-based access control
- TYPE_REGISTRY_DESIGN.md: Type registry architecture
- REFACTORING_COMPLETE.md: Overall refactoring summary
- TESTS_COMPLETE.md: Testing documentation
Build Status: ✅ Compiles successfully with minor warnings
4.6 KiB
4.6 KiB
Signatory-Based Access Control for OSIRIS Contexts
Overview
OSIRIS contexts now use signatory-based access control instead of owner-based permissions. This means that access to a context is granted only if all participants are signatories of the Rhai script.
Key Changes
1. Removed Owner Field
OsirisContextno longer has anowner_idfield- Replaced with
participants: Vec<String>- a list of public keys
2. Context Identification
- Context ID is now a sorted, comma-separated list of participant public keys
- Example:
"pk1,pk2,pk3"for a context with three participants - Sorting ensures consistent IDs regardless of input order
3. Access Control via SIGNATORIES
get_context()function checks theSIGNATORIEStag in the Rhai execution context- All requested participants must be present in the SIGNATORIES list
- If any participant is not a signatory, access is denied
API Changes
Rhai Script Usage
Old way (deprecated):
let ctx = osiris("context_name", "owner_id", "redis://localhost:6379", 1);
New way:
// Single participant
let ctx = get_context(["pk1"]);
// Multiple participants (shared context)
let ctx = get_context(["pk1", "pk2", "pk3"]);
Setting Up SIGNATORIES
When creating a Rhai engine, you must set up the SIGNATORIES tag:
use rhai::{Engine, Dynamic, Map, Array};
let mut engine = create_osiris_engine("redis://localhost:6379", 1)?;
// Create context tags
let mut tag_map = Map::new();
// SIGNATORIES must be a Rhai array of strings
let signatories: Array = vec![
Dynamic::from("pk1".to_string()),
Dynamic::from("pk2".to_string()),
Dynamic::from("pk3".to_string()),
];
tag_map.insert("SIGNATORIES".into(), Dynamic::from(signatories));
tag_map.insert("DB_PATH".into(), "/path/to/db".to_string().into());
tag_map.insert("CONTEXT_ID".into(), "script_context".to_string().into());
engine.set_default_tag(Dynamic::from(tag_map));
Access Control Flow
- Script Execution: Rhai script calls
get_context(["pk1", "pk2"]) - Extract SIGNATORIES: Function reads
SIGNATORIESfrom context tag - Verify Participants: Checks that all participants (
pk1,pk2) are in SIGNATORIES - Grant/Deny Access:
- ✅ If all participants are signatories → create/return context
- ❌ If any participant is missing → return error
Example: Shared Context
// Three people want to collaborate
// All three must have signed the script
let shared_ctx = get_context(["alice_pk", "bob_pk", "charlie_pk"]);
// Now all three can access the same data
shared_ctx.save("notes", "note1", #{
title: "Meeting Notes",
content: "Discussed project timeline"
});
// Context ID will be: "alice_pk,bob_pk,charlie_pk" (sorted)
print(shared_ctx.context_id());
Builder API Changes
Old API (deprecated):
OsirisContext::builder()
.name("context_name")
.owner("owner_id") // Deprecated
.herodb_url("redis://localhost:6379")
.db_id(1)
.build()?
New API:
OsirisContext::builder()
.participants(vec!["pk1".to_string(), "pk2".to_string()])
.herodb_url("redis://localhost:6379")
.db_id(1)
.build()?
Member Management
All participants automatically get admin privileges in the context:
Privilege::AdminPrivilege::ReadPrivilege::WritePrivilege::ManageMembers
Additional members can still be added with custom privileges:
let ctx = get_context(["pk1", "pk2"]);
ctx.add_member("pk3", ["read", "write"]);
Security Benefits
- Multi-signature Support: Contexts can be shared between multiple parties
- Script-level Authorization: Access control is enforced at script execution time
- No Hardcoded Owners: Flexible participant model
- Transparent Access: All participants have equal rights by default
Testing
Tests verify:
- ✅ Valid signatories can create contexts
- ✅ Invalid signatories are denied access
- ✅ Context IDs are properly sorted
- ✅ Multiple participants work correctly
Run tests:
cargo test --lib --features rhai-support
Migration Guide
If you have existing code using the old API:
-
Replace
owner()withparticipants():// Old .owner("user_id") // New .participants(vec!["user_id".to_string()]) -
Update Rhai scripts:
// Old let ctx = osiris("name", "owner", "url", 1); // New let ctx = get_context(["owner"]); -
Set up SIGNATORIES tag in your engine configuration
-
Update tests to use the new API
All core functionality tested and verified! 🎉