Files
osiris/SIGNATORY_ACCESS_CONTROL.md
Timur Gordon e04012c8c0 Refactor Rhai integration with context-based execution and type registry
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
2025-10-28 03:33:39 +01:00

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!** 🎉