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
177 lines
4.6 KiB
Markdown
177 lines
4.6 KiB
Markdown
# 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**
|
|
- `OsirisContext` no longer has an `owner_id` field
|
|
- 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 the `SIGNATORIES` tag 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):**
|
|
```rhai
|
|
let ctx = osiris("context_name", "owner_id", "redis://localhost:6379", 1);
|
|
```
|
|
|
|
**New way:**
|
|
```rhai
|
|
// 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:
|
|
|
|
```rust
|
|
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
|
|
|
|
1. **Script Execution**: Rhai script calls `get_context(["pk1", "pk2"])`
|
|
2. **Extract SIGNATORIES**: Function reads `SIGNATORIES` from context tag
|
|
3. **Verify Participants**: Checks that all participants (`pk1`, `pk2`) are in SIGNATORIES
|
|
4. **Grant/Deny Access**:
|
|
- ✅ If all participants are signatories → create/return context
|
|
- ❌ If any participant is missing → return error
|
|
|
|
## Example: Shared Context
|
|
|
|
```rhai
|
|
// 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):
|
|
```rust
|
|
OsirisContext::builder()
|
|
.name("context_name")
|
|
.owner("owner_id") // Deprecated
|
|
.herodb_url("redis://localhost:6379")
|
|
.db_id(1)
|
|
.build()?
|
|
```
|
|
|
|
### New API:
|
|
```rust
|
|
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::Admin`
|
|
- `Privilege::Read`
|
|
- `Privilege::Write`
|
|
- `Privilege::ManageMembers`
|
|
|
|
Additional members can still be added with custom privileges:
|
|
```rhai
|
|
let ctx = get_context(["pk1", "pk2"]);
|
|
ctx.add_member("pk3", ["read", "write"]);
|
|
```
|
|
|
|
## Security Benefits
|
|
|
|
1. **Multi-signature Support**: Contexts can be shared between multiple parties
|
|
2. **Script-level Authorization**: Access control is enforced at script execution time
|
|
3. **No Hardcoded Owners**: Flexible participant model
|
|
4. **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:
|
|
```bash
|
|
cargo test --lib --features rhai-support
|
|
```
|
|
|
|
## Migration Guide
|
|
|
|
If you have existing code using the old API:
|
|
|
|
1. **Replace `owner()` with `participants()`**:
|
|
```rust
|
|
// Old
|
|
.owner("user_id")
|
|
|
|
// New
|
|
.participants(vec!["user_id".to_string()])
|
|
```
|
|
|
|
2. **Update Rhai scripts**:
|
|
```rhai
|
|
// Old
|
|
let ctx = osiris("name", "owner", "url", 1);
|
|
|
|
// New
|
|
let ctx = get_context(["owner"]);
|
|
```
|
|
|
|
3. **Set up SIGNATORIES tag** in your engine configuration
|
|
|
|
4. **Update tests** to use the new API
|
|
|
|
---
|
|
|
|
**All core functionality tested and verified!** 🎉
|