# How MiroFish Tracks and Associates Simulations with Specific Projects

> Discover how MiroFish tracks simulations by associating them with projects using a project ID. Learn how this ensures durable linkage for your simulation data.

- Repository: [BaiFu/mirofish](https://github.com/666ghj/mirofish)
- Tags: how-to-guide
- Published: 2026-02-23

---

**The MiroFish backend tracks and associates simulations with specific projects by storing a `project_id` field in the `SimulationState` dataclass and persisting that relationship to a JSON file on disk, ensuring durable linkage across server restarts.**

The 666ghj/mirofish repository implements a robust backend architecture that tracks and associates simulations with specific projects through persistent storage mechanisms. By embedding unique project identifiers directly into simulation state objects and serializing them to structured JSON files, the system maintains reliable relationships between computational workflows and their originating project metadata.

## Project and Simulation Data Models

### Project Persistence Architecture

In [`backend/app/models/project.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/models/project.py), the `Project` dataclass defines the metadata structure for projects, including fields for id, name, status, and associated files. The `ProjectManager` class generates a unique `project_id` using the format `proj_<12‑hex>` and persists the entire model to [`project.json`](https://github.com/666ghj/mirofish/blob/main/project.json) under the directory `UPLOAD_FOLDER/projects/<project_id>/`.

### Simulation State Structure

The `SimulationState` dataclass in [`backend/app/services/simulation_manager.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/services/simulation_manager.py) contains the critical `project_id: str` field that establishes the association between a simulation and its parent project. This field is populated during simulation creation and maintained throughout the simulation lifecycle within the state object.

## How the Project Manager Creates the Association

### Generating Unique Project Identifiers

When `ProjectManager.create_project()` is invoked, it generates a unique 12-character hexadecimal identifier prefixed with `proj_`. This identifier serves as the canonical reference stored in the project's JSON file and subsequently referenced by all associated simulations.

### Linking Simulations via project_id

The `SimulationManager.create_simulation()` method accepts a `project_id` parameter, which it injects into the `SimulationState` dataclass during instantiation. This creates the in-memory association that is subsequently persisted to disk through the `_save_simulation_state()` method.

## Persistent Storage Implementation

### File System Layout

The backend maintains separate directory structures for projects and simulations. Projects reside in `UPLOAD_FOLDER/projects/<project_id>/project.json`, while simulations store their state in `uploads/simulations/<simulation_id>/state.json`. The `project_id` field within [`state.json`](https://github.com/666ghj/mirofish/blob/main/state.json) maintains the cross-reference between these storage locations.

### State Serialization

The `_save_simulation_state()` method in `SimulationManager` serializes the entire `SimulationState` object—including the `project_id`—to JSON format. This ensures the project-simulation association survives server restarts, crashes, or deployments across multiple workers.

## Retrieving Project-Simulation Relationships

To resolve which project owns a specific simulation, `SimulationManager.get_simulation(simulation_id)` loads the corresponding [`state.json`](https://github.com/666ghj/mirofish/blob/main/state.json) file from disk, reconstructs the `SimulationState` object, and exposes the stored `project_id`. API endpoints in [`backend/app/api/simulation.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/api/simulation.py) leverage this method to answer project affiliation queries and enforce project-based access controls.

## Complete Workflow Example

The following examples demonstrate creating a project, associating a simulation, and retrieving the relationship.

### Creating a Project and Linked Simulation

```python
from backend.app.models.project import ProjectManager
from backend.app.services.simulation_manager import SimulationManager

# 1️⃣ Create a new project

project = ProjectManager.create_project(name="Social Media Analysis")
print("Project ID:", project.project_id)   # e.g. proj_9f3a8b7c2d1e

# 2️⃣ Initialise the simulation manager

sim_mgr = SimulationManager()

# 3️⃣ Create a simulation that belongs to the project

sim_state = sim_mgr.create_simulation(
    project_id=project.project_id,
    graph_id="graph_12345",          # ID of the Zep graph that stores the knowledge base

    enable_twitter=True,
    enable_reddit=False,
)

print("Simulation ID:", sim_state.simulation_id)
print("Linked Project ID:", sim_state.project_id)   # matches the project above

```

### Retrieving the Project from a Simulation

```python

# Load an existing simulation

sim_state = sim_mgr.get_simulation("sim_a1b2c3d4e5f6")
if sim_state:
    # Use the stored project_id to fetch the project details

    project = ProjectManager.get_project(sim_state.project_id)
    print(f"Simulation {sim_state.simulation_id} belongs to project '{project.name}'")

```

### API-Level Lookup

```python

# Inside a Flask route (simplified)

def get_simulation_info(simulation_id: str):
    state = SimulationManager().get_simulation(simulation_id)
    project = ProjectManager.get_project(state.project_id)
    return {
        "simulation_id": state.simulation_id,
        "project_id": project.project_id,
        "project_name": project.name,
        "status": state.status,
    }

```

## Key Implementation Files

- **[`backend/app/models/project.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/models/project.py)** – Defines the `Project` dataclass, `ProjectStatus` enumeration, and `ProjectManager` class responsible for generating unique `project_id` values and persisting project metadata to JSON files.

- **[`backend/app/services/simulation_manager.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/services/simulation_manager.py)** – Contains the `SimulationState` dataclass with the critical `project_id` field, the `SimulationManager` class, and methods including `create_simulation()`, `get_simulation()`, and `_save_simulation_state()` that handle JSON serialization of project associations.

- **[`backend/app/api/simulation.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/api/simulation.py)** – Flask API endpoints that expose simulation data and project relationships to clients, utilizing `SimulationManager` to resolve `project_id` associations and enforce project-based access controls.

- **[`backend/config.py`](https://github.com/666ghj/mirofish/blob/main/backend/config.py)** – Configuration module providing `UPLOAD_FOLDER` and `OASIS_SIMULATION_DATA_DIR` paths that define the physical directory structure where project and simulation state files reside.

## Summary

- The MiroFish backend tracks and associates simulations with specific projects by storing a `project_id` field in the `SimulationState` dataclass defined in [`backend/app/services/simulation_manager.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/services/simulation_manager.py).
- Project identifiers follow the format `proj_<12‑hex>` and persist to `UPLOAD_FOLDER/projects/<project_id>/project.json` via the `ProjectManager` class.
- Simulation state—including the project association—serializes to `uploads/simulations/<simulation_id>/state.json` through the `_save_simulation_state()` method.
- The `SimulationManager` provides `create_simulation()` and `get_simulation()` methods to establish and resolve project relationships at runtime.
- API endpoints in [`backend/app/api/simulation.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/api/simulation.py) expose these relationships to clients, enabling project-based simulation management and access control.

## Frequently Asked Questions

### How does MiroFish ensure the project-simulation link survives server restarts?

MiroFish persists the association in JSON files on disk rather than relying solely on runtime memory. The `project_id` is stored inside [`state.json`](https://github.com/666ghj/mirofish/blob/main/state.json) within the simulation's directory (`uploads/simulations/<simulation_id>/`), and the `_save_simulation_state()` method writes this file whenever the simulation state changes. When the server restarts, `get_simulation()` reloads the JSON and reconstructs the `SimulationState` object, restoring the link.

### What is the format of the project_id used to link simulations?

The `ProjectManager` generates unique identifiers using the format `proj_<12‑hex>`, where `<12‑hex>` represents a 12-character hexadecimal string. This format ensures uniqueness while remaining human-readable. The generated ID is stored in the project's [`project.json`](https://github.com/666ghj/mirofish/blob/main/project.json) file and subsequently referenced by the `project_id` field in `SimulationState` when `create_simulation()` is invoked.

### Can a simulation be transferred to a different project after creation?

Based on the current implementation in [`backend/app/services/simulation_manager.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/services/simulation_manager.py), the `project_id` is set during `create_simulation()` and stored as a field in the `SimulationState` dataclass. While the `_save_simulation_state()` method could theoretically overwrite the JSON file with modified data, the standard API in [`backend/app/api/simulation.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/api/simulation.py) does not expose endpoints to modify the `project_id` field after initial creation. Consequently, simulations remain bound to their originating project for their entire lifecycle.

### Which source files contain the core logic for tracking project-simulation associations?

The primary implementation resides in three key files: [`backend/app/models/project.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/models/project.py) defines the `ProjectManager` class responsible for generating project IDs and persisting project metadata; [`backend/app/services/simulation_manager.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/services/simulation_manager.py) contains the `SimulationState` dataclass with the `project_id` field and the `SimulationManager` methods that serialize this relationship to disk; and [`backend/app/api/simulation.py`](https://github.com/666ghj/mirofish/blob/main/backend/app/api/simulation.py) exposes these relationships through REST API endpoints. Configuration paths defined in [`backend/config.py`](https://github.com/666ghj/mirofish/blob/main/backend/config.py) determine the physical directory structure where these associations are stored.