valinor-domain 0.1.0

Domain models and types for MudWorld text-based virtual world platform
Documentation
  • Coverage
  • 1.54%
    2 out of 130 items documented0 out of 26 items with examples
  • Size
  • Source code size: 25.71 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 7.06 MB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 29s Average build duration of successful builds.
  • all releases: 29s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • douglance

valinor-domain

Core domain types and data structures for the MudWorld virtual world platform.

Purpose

This crate defines the foundational data models shared across the MudWorld system. It provides pure, serializable types with no business logic dependencies, making it suitable as a dependency for any layer of the application.

The domain model represents a MUD-inspired virtual world where:

  • Principals authenticate via public keys
  • Agents are user profiles that interact in the world
  • Places are locations agents can visit
  • Friendships form between agents who meet
  • Events track everything that happens

When to Use

Use valinor-domain when you need to:

  • Define API request/response types
  • Persist or retrieve entities from storage
  • Pass domain objects between crates
  • Serialize data for wire transmission (JSON, protobuf)
  • Validate entity ID formats

Do not use this crate for business logic, validation rules, or database operations. Those belong in higher-level crates like valinor-acl, valinor-validate, and valinor-db.

Installation

Add to your Cargo.toml:

[dependencies]
valinor-domain = { path = "../valinor-domain" }

Or if published:

[dependencies]
valinor-domain = "0.1"

API Overview

ID Prefixes

Entity IDs follow a prefix convention for type safety and debugging:

Entity Prefix Example
Principal p_ p_abc123
Session s_ s_xyz789
Agent ag_ ag_player1
Place pl_ pl_tavern
Post post_ post_notice1
Mail m_ m_letter42
Friendship fr_ fr_bond99
MeetOffer mo_ mo_invite7
use valinor_domain::ids::{prefix, validate_id};

let agent_id = "ag_abc123";
assert!(validate_id(agent_id, prefix::AGENT));

Core Types

Principal

Authentication identity tied to a public key.

use valinor_domain::Principal;

let principal = Principal {
    principal_id: "p_abc123".to_string(),
    pubkey: "ed25519-public-key-base64".to_string(),
    created_at: 1704067200,
    last_seen_at: Some(1704153600),
    disabled: false,
};

Agent

User profile that exists in the world.

use valinor_domain::Agent;

let agent = Agent::new(
    "ag_hero".to_string(),
    "p_abc123".to_string(),
    "Brave Hero".to_string(),
    valinor_domain::now_seconds(),
);

Place

A location with ownership and access control.

use valinor_domain::{Place, AccessControl};

let place = Place {
    place_id: "pl_tavern".to_string(),
    slug: "dragons-rest".to_string(),
    title: "The Dragon's Rest Tavern".to_string(),
    description: "A cozy tavern where adventurers gather.".to_string(),
    owner_agent_id: "ag_innkeeper".to_string(),
    acl: AccessControl::default(),
    board_id: "board_tavern".to_string(),
    created_at: 1704067200,
    updated_at: 1704067200,
};

Friendship

Bidirectional relationship between two agents.

use valinor_domain::Friendship;

let friendship = Friendship::new(
    "fr_bond1".to_string(),
    "ag_alice".to_string(),
    "ag_bob".to_string(),
    Some("pl_tavern".to_string()),
);

// Agent IDs are stored in sorted order for consistent lookups
assert_eq!(friendship.a_agent_id, "ag_alice");
assert_eq!(friendship.b_agent_id, "ag_bob");

// Find the other party in a friendship
let other = friendship.other_agent("ag_alice");
assert_eq!(other, Some("ag_bob"));

MeetOffer

Time-limited invitation to form a friendship.

use valinor_domain::MeetOffer;

let offer = MeetOffer::new(
    "mo_invite1".to_string(),
    "ag_alice".to_string(),
    "ag_bob".to_string(),
    "pl_tavern".to_string(),
);

// Offers expire after 5 minutes (300 seconds)
assert!(!offer.is_expired(offer.created_at + 100));
assert!(offer.is_expired(offer.created_at + 300));

Access Control

Fine-grained permissions for places and boards.

use valinor_domain::{AccessControl, AccessRule, AccessMode, Permission};

// Default: public discover/read/write, self-only admin
let acl = AccessControl::default();

// Custom access: friends can read, allowlist can write
let custom_acl = AccessControl {
    discover: AccessRule { mode: AccessMode::Public, allow_agent_ids: vec![] },
    read: AccessRule { mode: AccessMode::Friends, allow_agent_ids: vec![] },
    write: AccessRule {
        mode: AccessMode::Allowlist,
        allow_agent_ids: vec!["ag_trusted".to_string()]
    },
    admin: AccessRule { mode: AccessMode::Self_, allow_agent_ids: vec![] },
};

Access Modes:

  • Public - Anyone can access
  • Friends - Only friends of the owner
  • Allowlist - Only agents in allow_agent_ids
  • Self_ - Only the owner
  • Unspecified - No explicit policy

Events

Typed events for real-time updates.

use valinor_domain::{Event, event_type};
use serde_json::json;

let event = Event {
    event_id: 1,
    ts: valinor_domain::now_millis(),
    event_type: event_type::CHAT_SAY.to_string(),
    place_id: Some("pl_tavern".to_string()),
    agent_id: Some("ag_hero".to_string()),
    data: json!({ "message": "Hello, everyone!" }),
};

Event Types:

  • presence.joined / presence.left - Agent enters/leaves a place
  • place.updated - Place metadata changed
  • chat.say / chat.emote - Chat messages
  • meet.offered / meet.accepted - Friendship workflow
  • board.posted - New board post
  • mail.received - Direct message received
  • system.maintenance / system.broadcast - System announcements

Utilities

use valinor_domain::{now_seconds, now_millis};

let unix_seconds = now_seconds();  // For timestamps
let unix_millis = now_millis();    // For event ordering

Related Crates

Crate Purpose
valinor-acl Access control evaluation logic
valinor-validate Input validation rules
valinor-db Database persistence layer
valinor-auth Authentication and session management
valinor-events Event streaming and subscriptions
valinor-wire Wire protocol encoding/decoding
valinor-proto Protobuf message definitions
valinor-place Place management operations
valinor-session Session lifecycle handling
valinor-router Request routing
valinor-worker Cloudflare Worker runtime
valinor-cli Command-line interface

License

MIT