All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[0.2.7] - 2026-06-26

Added

  • Injector strict_mode support: OrchidSymbiont.Hooks.Injector now reads :strict_mode from the workflow baggage. When strict_mode: true, the resolver will not fall back to the global catalog, ensuring strict multi-tenant isolation at the hook level.

    Orchid.run(recipe, params,
      baggage: %{scope_id: "tenant-1", strict_mode: true}
    )

[0.2.5] & [0.2.6] - 2026-04-24

Enhenced

  • Documents: Updated documents.

[0.2.4] - 2026-03-26

Enhenced

  • Symbiont ID Type: Now Symbiont's ID also support binary. If the name is dynamically generated in your application, it is recommended to use binary instead of atom to avoid memory leaks.

Changed

  • Scopa Name Declaration: Now we use :scope_id instead :session_id to seperate domains.

Migration Guide (0.2.3 -> 0.2.4)

# Before
{OrchidSymbiont.Runtime, session_id: "my_session"}
OrchidSymbiont.register("my_session", :worker, {MyWorker, []})
Orchid.WorkflowCtx.put_baggage(:session_id, "my_session")
# After
{OrchidSymbiont.Runtime, scope_id: "my_session"}
OrchidSymbiont.register("my_session", :worker, {MyWorker, []})
Orchid.WorkflowCtx.put_baggage(:scope_id, "my_session")

[0.2.3] - 2026-03-25

Fix

  • Fixed a bug where adding options other than session_id would prevent the creation of additional processes.

[0.2.2] - 2026-03-25

Added

  • Strict Mode: A new strict_mode: true option has been added to OrchidSymbiont.Resolver.resolve/3. When enabled, if the corresponding service blueprint is not found in the current Session's Catalog, an error will be thrown directly, and there will be no fallback to the global Catalog, thus ensuring stricter multi-tenant security isolation.

  • State Backup and Restore: The dump/1 and restore/2 methods have been added to OrchidSymbiont.Catalog for easy exporting and restoring of the current Catalog's state.

Changed

  • [Architecture Refactoring] True Session Isolation: The Session's supervised tree model has been refactored. Now, when you start a Session using OrchidSymbiont.Runtime, it launches a dedicated OrchidSymbiont.Catalog process for that Session. Registration states between different Sessions are now truly physically isolated, instead of being distinguished by tuples {{session_id, name}, val} in the global state.

  • [Performance Optimization] Catalog Underlying Replacement: The underlying implementation of OrchidSymbiont.Catalog has been simplified from GenServer to Agent, making it more lightweight and better suited to its pure state storage nature.

  • **Startup Layer Optimization: The application startup process has been streamlined. The bloated list of child processes in OrchidSymbiont.Application has been removed. The startup logic for global services (Registry, global Catalog, DynamicSupervisor, Preloader) is now consolidated and wrapped within the :global initialization strategy of OrchidSymbiont.Runtime.

Removed

  • Removed clear/0 and clear_session/1 in OrchidSymbiont.Catalog module. Since Sessions now manage their lifecycle through an independent supervision tree, their internal Catalog processes are automatically destroyed and reclaimed when the corresponding Runtime terminates, eliminating the need for manual cleanup.

[0.2.1] - 2026-03-24

BREAKING CHANGE

Fixed

  • Atom Exhaustion Vulnerability: Resolved a critical memory leak issue where dynamic session IDs (atoms) were never garbage collected, potentially causing VM crashes in long-running multi-tenant applications.

Changed

  • Session ID Type: Changed session_id from atom() to binary() (String). Example: :project_a"project_a".
  • Unified Registry Architecture: Replaced per-session Registry/Catalog/Preloader processes with a single global Registry using compound keys {session_id, name}. This significantly reduces process overhead for high-session-count scenarios.
  • Runtime Implementation: Orchid.Symbiont.Runtime now uses DynamicSupervisor directly instead of wrapping it in a Supervisor.
  • Simplified Naming Module: Refactored Orchid.Symbiont.Naming with cleaner API:
    • get_registry/0 - Returns the unified registry
    • session_supervisor/1 - Returns via tuple for session supervisor
    • worker/2 - Returns via tuple for session workers

Removed

  • Per-session Registry processes (now uses global with compound keys)
  • Per-session Catalog processes (now uses single global instance)
  • Per-session Preloader processes (now uses global Orchid.Symbiont.Preloader)
  • Naming.registry/1, Naming.catalog/1, Naming.preloader/1 functions

Migration Guide (0.2.0 → 0.2.1)

# Before (0.2.0)
{Orchid.Symbiont.Runtime, session_id: :my_session}
Orchid.Symbiont.register(:my_session, :worker, {MyWorker, []})
Orchid.WorkflowCtx.put_baggage(:session_id, :my_session)

# After (0.2.1)
{OrchidSymbiont.Runtime, session_id: "my_session"}
OrchidSymbiont.register("my_session", :worker, {MyWorker, []})
Orchid.WorkflowCtx.put_baggage(:session_id, "my_session")

[0.2.0] - 2026-01-04

Added

  • Session Isolation (Multi-Tenancy): Introduced the ability to run completely isolated sandboxes of Symbiont processes using session_id. Perfect for concurrent workflows or multi-tenant SaaS architectures without PID conflicts.
  • Dynamic Supervision Trees: Orchid.Symbiont.Runtime can now be started multiple times under different namespaces by passing [session_id: :your_session_name]. Each session gets its own isolated Registry, DynamicSupervisor, Catalog, and Preloader.
  • Smart Catalog Fallback: Added a hierarchical lookup mechanism in Orchid.Symbiont.Catalog. If a blueprint is not found in a session-specific catalog, it will automatically fall back to the global catalog. (Write blueprints once globally, run instances locally!)
  • New Naming Module: Added Orchid.Symbiont.Naming to handle dynamic process registration routing transparently.

Changed

  • Injector Hook Upgraded: Orchid.Symbiont.Hooks.Injector now automatically extracts :session_id from the Orchid.WorkflowCtx baggage and routes the process resolution to the corresponding session's registry.
  • API Enhancements: Orchid.Symbiont.register and Orchid.Symbiont.Resolver.resolve now accept an optional session_id parameter. (Fully backward compatible with global singleton usage).
  • Dependencies Bump: Updated orchid to 0.5.6, telemetry to 1.4.1, and ex_doc to 0.40.1.

[0.1.4] - 2026-01-03

Added

  • Global Mapping Support: Orchid.Symbiont.Hooks.Injector now supports resolving symbiont aliases from the Orchid.WorkflowCtx baggage.
  • Hierarchical Resolution: Symbiont mappings are now merged from two levels:
    1. Global: Set via Orchid.WorkflowCtx.put_baggage(ctx, :symbiont_mapper, [...]).
    2. Local: Set via step_opts. Note: Local step-specific mappings will override global mappings if both define the same logical name.

Fixed

  • Internal get_headers logic in the Injector hook to properly handle the workflow context.

[0.1.3] - 2026-01-02

Changed

  • Breaking: Renamed Orchid.Symbiont.Step.get_required/0 with old name called get_step_required_mapper/0 for shorter and cleaner API usage.
  • Orchid.Symbiont.call/3 now uses apply/3 for dynamic module invocation.

Added

  • Orchid.Symbiont.preload/1 now accepts a single symbiont name in addition to a list of names.

[0.1.2] - 2026-01-02

Dependencies

  • update orchid's version to 0.5

[0.1.1] - 2025-12-27

Dependencies

  • use a looser version constraint for better compatibility with future patch releases

[0.1.0] - 2025-12-26

Added

  • Initial Release: Launched OrchidSymbiont as the official process management extension for the Orchid workflow engine.
  • Lazy Loading: Introduced a mechanism to start GenServers (Symbionts) only when requested by a workflow step, optimizing resource usage for heavy tasks (e.g., ML models, DB connections).
  • Dependency Injection: Added Orchid.Symbiont.Hooks.Injector to automatically resolve and inject running process references (PIDs) into Steps implementing the Orchid.Symbiont.Step behavior.
  • Lifecycle Management (TTL):
    • Implemented an Idle Shutdown mechanism using a transparent Wrapper/Proxy pattern.
    • Workers configured with a :ttl option will automatically terminate after a period of inactivity to free up resources.
    • The Wrapper ensures request forwarding is transparent and handles timeouts (:infinity internally) correctly to support long-running tasks.
  • Registry & Catalog:
    • Orchid.Symbiont.register/2: API to define blueprints for services, supporting both standard startup and TTL-enabled modes.
    • Built-in Registry for name resolution and idempotency check (preventing duplicate startups).
  • Integration:
    • Provides Orchid.Symbiont.Step behavior requiring required/0 (dependencies) and run_with_model/3 (execution logic).
    • Added helper Orchid.Symbiont.call/3 for ergonomic synchronous communication with Symbionts.

Dependencies

  • Requires Orchid ~> 0.4.0 (utilizes the new Context and Hook architecture).