Models Specification
Freeflow Universe – mycojobs
This document gathers all data‑models that exist in the lib/mycojobs/model/ package, together with a concise purpose description, field semantics, Redis storage layout and the role each model plays in the overall decentralised workflow architecture.
Table of Contents
- Actor
- Context
- Flow
- Message
- Runner
- RunnerJob
- Enums & Shared Types
- Key‑generation helpers
1️⃣ Actor – Identity & entry‑point
| Field |
Type |
Description |
id |
u32 |
Sequential identifier unique per tenant. Used as part of the Redis key actor:<id>. |
pubkey |
string |
Public key (Mycelium‑compatible) that authenticates the actor when it sends/receives messages. |
address |
[]Address |
One or more reachable addresses (normally Mycelium topics) that other participants can use to contact the actor. |
created_at |
u32 |
Unix‑epoch time when the record was created. |
updated_at |
u32 |
Unix‑epoch time of the last mutation. |
Purpose
- An Actor is the human‑or‑service that requests work, receives results and can be an administrator of a Context.
- It is the security principal – every operation in a context is authorised against the actor’s ID and its public key signature.
Redis representation
| Key |
Example |
Storage type |
Fields |
actor:${id} |
actor:12 |
hash (HSET) |
id, pubkey, address (list), created_at, updated_at |
2️⃣ Context – Tenant & permission container
| Field |
Type |
Description |
id |
u32 |
Identifier that also selects the underlying Redis DB for this tenant. |
admins |
[]u32 |
Actor IDs that have full control (create/delete any object, manage permissions). |
readers |
[]u32 |
Actor IDs that may read any object in the context but cannot modify. |
executors |
[]u32 |
Actor IDs allowed to run RunnerJobs and update their status. |
created_at |
u32 |
Unix‑epoch of creation. |
updated_at |
u32 |
Unix‑epoch of last modification. |
Purpose
- A Context isolates a tenant – each tenant gets its own Redis database and a dedicated filesystem area (for logs, temporary files, …).
- It stores permission lists that the system consults before any operation (e.g., creating a
Flow, enqueuing a RunnerJob).
Redis representation
| Key |
Example |
Storage type |
Fields |
context:${id} |
context:7 |
hash |
id, admins, readers, executors, created_at, updated_at |
3️⃣ Flow – High‑level workflow (DAG)
| Field |
Type |
Description |
id |
u32 |
Flow identifier – unique inside the creator’s actor space. |
caller_id |
u32 |
Actor that created the flow (owner). |
context_id |
u32 |
Context in which the flow lives. |
jobs |
[]u32 |
List of RunnerJob IDs that belong to this flow (the DAG edges are stored in each job’s dependends). |
env_vars |
map[string]string |
Global environment variables injected into every job of the flow. |
result |
map[string]string |
Aggregated output produced by the flow (filled by the orchestrator when the flow finishes). |
created_at |
u32 |
Creation timestamp. |
updated_at |
u32 |
Last update timestamp. |
status |
FlowStatus |
Current lifecycle stage (dispatched, started, error, finished). |
Purpose
- A Flow is the public‑facing representation of a workflow.
- It groups many
RunnerJobs, supplies common env‑vars, tracks overall status and collects the final result.
- Only the creator (the
caller_id) may mutate the flow definition.
Redis representation
| Key |
Example |
Storage type |
Fields |
flow:${id} |
flow:33 |
hash |
id, caller_id, context_id, jobs, env_vars, result, created_at, updated_at, status |
FlowStatus enum
| Value |
Meaning |
dispatched |
Flow has been stored but not yet started. |
started |
At least one job is running. |
error |
One or more jobs failed; flow aborted. |
finished |
All jobs succeeded, result is final. |
4️⃣ Message – Transport unit (Mycelium)
| Field |
Type |
Description |
id |
u32 _type |
ScriptType |
message_format_type |
MessageFormatType |
Formatting of message (html, text, md). |
timeout |
u32 |
Seconds before the message is considered lost if not delivered. |
timeout_ack |
u32 |
Seconds allowed for the receiver to acknowledge. |
timeout_result |
u32 |
Seconds allowed for the receiver to send back a result. |
job |
[]Job |
Embedded RunnerJob objects (normally a single job). |
logs |
[]Log |
Optional streaming logs attached to the message. |
created_at |
u32 |
Timestamp of creation. |
updated_at |
u32 |
Timestamp of latest update. |
status |
MessageStatus |
Current lifecycle (dispatched, acknowledged, error, processed). |
Purpose
-
Message is the payload carrier that travels over Mycelium (the pub/sub system).
-
It can be a job request, a chat line, an email, or any generic data that needs to be routed between actors, runners, or services.
-
Every message is persisted as a Redis hash; the system also maintains two generic queues:
msg_out – outbound messages waiting to be handed to Mycelium.
msg_in – inbound messages that have already arrived and are awaiting local processing.
Redis representation
| Key |
Example |
Storage type |
Fields |
message:${caller_id}:${id} |
message:12:101 |
hash |
All fields above (id, caller_id, context_id, …, status). |
MessageType enum (legacy – not used in current code but documented)
| Value |
Meaning |
job |
Payload carries a RunnerJob. |
chat |
Human‑to‑human communication. |
mail |
Email‑like message. |
MessageFormatType enum
| Value |
Meaning |
html |
HTML formatted body. |
text |
Plain‑text. |
md |
Markdown. |
MessageStatus enum
| Value |
Meaning |
dispatched |
Stored, not yet processed. |
acknowledged |
Receiver has confirmed receipt. |
error |
Delivery or processing failed. |
| ` |
Message handled (e.g., job result returned). |
5️⃣ Runner – Worker that executes jobs
| Field |
Type |
Description |
id |
u32 |
Unique runner identifier. |
pubkey |
string |
Public key of the runner (used by Mycelium for auth). |
address |
string |
Mycelium address (e.g., mycelium://…). |
topic |
string |
Pub/Sub topic the runner subscribes to; defaults to runner${id}. |
local |
bool |
If true, the runner also consumes jobs directly from Redis queues (e.g., queue:v). |
created_at |
u32 |
Creation timestamp. |
updated_at |
u32 |
Last modification timestamp. |
Purpose
- A Runner is the execution engine – it could be a VM, a container, or a process that knows how to run a specific script type (
v, python, osis, rust).
- It subscribes to a Mycelium topic to receive job‑related messages, and, when
local==true, it also polls a Redis list named after the script‑type (queue:<suffix>).
Redis representation
| Key |
Example |
Storage type |
runner:${id} |
runner:20 |
hash (all fields above) |
RunnerType enum
| Value |
Intended runtime |
v |
V language VM |
python |
CPython / PyPy |
osis |
OSIS‑specific runtime |
rust |
Native Rust binary |
6️⃣ RunnerJob – Executable unit
| Field |
Type |
Description |
id |
u32 |
Job identifier provided by the caller. |
caller_id |
u32 |
Actor that created the job. |
context_id |
u32 |
Context in which the job will run. |
script |
string |
Source code / command to be executed. |
script_type |
ScriptType |
Language or runtime of the script (osis, sal, v, python). |
timeout |
u32 |
Maximum execution time (seconds). |
retries |
u8 |
Number of automatic retries on failure. |
env_vars |
map[string]string |
Job‑specific environment variables (merged with Flow.env_vars). |
result |
map[string]string |
Key‑value map that the job writes back upon completion. |
prerequisites |
[]string |
Human‑readable IDs of external prerequisites (e.g., files, other services). |
dependends |
[]u32 |
IDs of other RunnerJob objects that must finish before this job can start. |
created_at |
u32 |
Creation timestamp. |
updated_at |
u32 |
Last update timestamp. |
status |
JobStatus |
Lifecycle status (dispatched, waiting_for_prerequisites, started, error, finished). |
Purpose
- A RunnerJob is the atomic piece of work that a
Runner executes.
- It lives inside a Context, is queued according to its
script_type, and moves through a well‑defined state machine.
- The
dependends field enables the DAG behaviour that the Flow model represents at a higher level.
Redis representation
| Key |
Example |
Storage type |
job:${caller_id}:${id} |
job:12:2001 |
hash (all fields above) |
ScriptType enum
| Value |
Runtime |
osis |
OSIS interpreter |
sal |
SAL DSL (custom) |
v |
V language |
python |
CPython / PyPy |
The enum provides a queue_suffix() helper that maps a script type to the name of the Redis list used for local job dispatch (queue:python, queue:v, …).
JobStatus enum
| Value |
Meaning |
dispatched |
Stored, waiting to be examined for prerequisites. |
waiting_for_prerequisites |
Has dependends that are not yet finished. |
started |
Currently executing on a runner. |
error |
Execution failed (or exceeded retries). |
finished |
Successfully completed, result populated. |
7️⃣ Other Enums & Shared Types
| Enum |
Location |
Values |
Note |
MessageType |
message.v |
job, chat, mail |
Determines how a Message is interpreted. |
MessageFormatType |
message.v |
html, text, md |
UI‑layer rendering hint. |
MessageStatus |
message.v |
dispatched, acknowledged, error, processed |
Life‑cycle of a Message. |
FlowStatus |
flow.v |
dispatched, started, error, finished |
High‑level flow progress. |
RunnerType |
runner.v |
v, python, osis, rust |
Not currently stored; used by the orchestration layer to pick a runner implementation. |
ScriptType |
runnerjob.v |
osis, sal, v, python |
Determines queue suffix & runtime. |
JobStatus |
runnerjob.v |
dispatched, waiting_for_prerequisites, started, error, finished |
Per‑job state machine. |
8️⃣ Key‑generation helpers (methods)
| Model |
Method |
Returns |
Example |
Actor |
redis_key() |
"actor:${self.id}" |
actor:12 |
Context |
redis_key() |
"context:${self.id}" |
context:7 |
Flow |
redis_key() |
"flow:${self.id}" |
flow:33 |
Message |
redis_key() |
"message:${self.caller_id}:${self.id}" |
message:12:101 |
Runner |
redis_key() |
"runner:${self.id}" |
runner:20 |
RunnerJob |
redis_key() |
"job:${self.caller_id}:${self.id}" |
job:12:2001 |
MessageType |
queue_suffix() |
"job" / "chat" / "mail" |
MessageType.job.queue_suffix() → "job" |
ScriptType |
queue_suffix() |
"osis" / "sal" / "v" / "python" |
ScriptType.python.queue_suffix() → "python" |
These helpers guarantee canonical key naming throughout the code base and simplify Redis interactions.
📌 Summary Diagram (quick reference)
context based
- Inside a Context, an Actor can create a Flow that references many RunnerJob IDs (the DAG).
- To initiate execution, the Actor packages a RunnerJob (or a full Flow) inside a Message, pushes it onto
msg_out, and the system routes it via Mycelium to the target Context.
- The remote Runner receives the Message, materialises the RunnerJob, queues it on a script‑type list, executes it, writes back
result and status, and optionally sends a result Message back to the originator.
All state is persisted as Redis hashes, guaranteeing durability and enabling idempotent retries. The uniform naming conventions (actor:<id>, job:<caller_id>:<id>, …) make it trivial to locate any object given its identifiers.