Skip to content

Conversation

@saxena-dev
Copy link
Owner

Phase 2 refactors the manja SDK from a single crate into a multi-crate
Cargo workspace. The new layout introduces clear boundaries between core
types, HTTP transport, WebSocket ticker, and WebDriver/TOTP login extras
while preserving the existing public facade via ManjaClient. The change
also wires feature flags and CI so that different dependency footprints
(websocket, webdriver-login, etc.) can be tested explicitly.

This PR corresponds to the Phase 2 backlog items:

  • PH2-T01 – Initialize Cargo workspace and member crates
  • PH2-T02 – Move shared types and errors into manja-core
  • PH2-T03 – Define reusable traits in manja-core
  • PH2-T04 – Move HTTP client and API groups into manja-http
  • PH2-T05 – Rewire ManjaClient to use manja-http
  • PH2-T06 – Move WebSocket ticker into manja-ticker
  • PH2-T07 – Move WebDriver login into manja-extras
  • PH2-T08 – Relocate and adjust tests across crates
  • PH2-T09 – Adjust examples to use workspace and facade
  • PH2-T10 – Document workspace architecture
  • PH2-T11 – Update CI to match workspace + feature matrix

Motivation

The original manja crate bundled all responsibilities into a single
package:

  • HTTP models, errors, and HTTP client
  • WebSocket ticker runtime
  • WebDriver-based login and TOTP helpers
  • Examples, tests, and ad-hoc utilities

This made the crate harder to evolve and heavier than necessary for many
use cases. Phase 2 addresses the architecture gaps outlined in
.data/artifacts/review-v0/01-architecture.md by:

  • Introducing a workspace and crate layering model (core types vs transport
    vs extras).
  • Enabling feature-flagged composition (e.g., HTTP-only vs HTTP+ticker vs
    WebDriver-enabled usage).
  • Preserving a stable, ergonomic facade (ManjaClient) for typical users,
    while offering lower-level crates for advanced consumers.

High-Level Changes

  • Converted the repo into a Cargo workspace with multiple member crates.
  • Extracted shared models, errors, and non-IO traits into a new manja-core
    crate.
  • Moved the HTTP client and domain API groups into a new manja-http crate.
  • Moved the WebSocket ticker into a new manja-ticker crate.
  • Moved WebDriver/TOTP login helpers into a new manja-extras crate.
  • Rewired manja to act as a facade over the other crates (via
    ManjaClient and manja::kite::*), gated by feature flags.
  • Updated tests, examples, README, and added ARCHITECTURE.md to describe
    the new workspace architecture.
  • Updated CI to run the feature matrix against the manja crate within the
    workspace.

Detailed Task Breakdown

PH2-T01 – Initialize Cargo workspace and member crates

  • Converted the root Cargo.toml into a workspace manifest with
    [workspace] and members:
    • manja
    • manja-core
    • manja-http
    • manja-ticker
    • manja-extras
  • Moved the original crate configuration into manja/Cargo.toml, making
    manja the primary facade crate within the workspace.
  • Added initial Cargo.toml and src/lib.rs stubs for the new crates to
    ensure the workspace builds end-to-end.

PH2-T02 – Move shared types and errors into manja-core

  • Created the manja-core crate with:
    • manja-core/src/lib.rs as the crate entry point.
    • manja-core/src/models/** hosting HTTP DTOs and enums that model Kite
      API responses and request structures (user/session, orders, portfolio,
      market, margins, etc.).
    • manja-core/src/error.rs defining core error types including
      KiteApiError and KiteApiException.
  • Moved model and error definitions from the monolithic manja crate into
    manja-core, updating imports throughout the workspace to use
    manja_core::models::* and manja_core::error::*.
  • Ensured manja-core does not depend on reqwest, Tokio, WebSocket, or
    WebDriver libraries, keeping it transport-agnostic and suitable for reuse
    in non-networked contexts.

PH2-T03 – Define reusable traits in manja-core

  • Added manja-core/src/traits.rs with non-IO, transport-agnostic traits:
    • CoreApiEndpoints – base/api/login/redirect URL accessors.
    • CoreCredentials – strongly-typed API key/secret, user ID/password,
      and TOTP key accessors (using Secret<String>).
    • CoreConfig – convenience trait alias combining endpoints and
      credentials.
    • CoreAuth and DefaultKiteAuth – helpers for constructing auth
      headers such as token {api_key}:{access_token}.
    • CoreLoginFlow – abstraction for async login flows that produce a
      request token, without tying to any particular runtime or driver.
  • Updated higher-level crates (manja, manja-http, manja-extras) to
    leverage these traits where appropriate, decoupling configuration and
    auth semantics from specific HTTP/WebDriver implementations.

PH2-T04 – Move HTTP client and API groups into manja-http

  • Created the manja-http crate with:
    • manja-http/src/lib.rs as the crate root with crate-level docs.
    • Modules for API groups, configuration, credentials, error handling, and
      utilities:
      • manja-http/src/api/** – typed API groups for Kite domains:
        Session, User, Orders, Portfolio, Market, Margins,
        Charges.
      • manja-http/src/client.rsHTTPClient implementation.
      • manja-http/src/config.rs, credentials.rs, utils.rs,
        error.rs, and test_utils.rs.
  • Moved HTTP-related logic from manja/src/kite/connect/** into
    manja-http, updating all imports to use manja-core types and the
    internal config/credentials types.
  • Ensured reqwest and backoff logic live solely in manja-http, so
    HTTP-specific dependencies are isolated to this crate.

PH2-T05 – Rewire ManjaClient to use manja-http

  • Implemented the ManjaClient facade in manja/src/client.rs:
    • Holds a manja_http::HTTPClient internally.
    • Provides new(Config) and from_env() constructors that delegate to
      the underlying HTTPClient configuration.
    • Exposes domain-specific accessors:
      • user(), session(), orders(), portfolio(), market(),
        margins(), charges().
  • Updated manja/src/lib.rs to:
    • Re-export ManjaClient.
    • Re-export key models and error types directly from manja-core so
      existing import patterns (e.g., use manja::UserProfile) continue to
      work.
    • Preserve the facade-first design introduced in Phase 1 while routing
      all HTTP calls through manja-http.

PH2-T06 – Move WebSocket ticker into manja-ticker

  • Created the manja-ticker crate:
    • manja-ticker/src/lib.rs with crate-level docs explaining its role as
      the WebSocket ticker implementation crate.
    • client, models, and stream modules for:
      • WebSocketClient and TickerStream.
      • StreamState and KiteStreamCredentials.
      • ticker Mode and TickerRequest types.
  • Updated the manja facade to:
    • Provide manja::kite::ticker as a thin re-export layer over
      manja-ticker when the websocket feature is enabled.
    • Keep ticker usage feature-gated and layered behind the facade for
      typical users.

PH2-T07 – Move WebDriver login into manja-extras

  • Created the manja-extras crate:
    • manja-extras/src/lib.rs with crate-level docs clarifying its role as
      an optional extras crate.
    • manja-extras/src/login/** containing:
      • chrome – WebDriver/Chrome launcher.
      • flow – browser-based login orchestration.
      • totp – Base32 + TOTP utilities.
      • errorLoginError and related result type.
  • Exposed high-level helpers from manja-extras:
    • browser_login_flow, launch_browser, generate_totp.
  • Wired the manja facade to:
    • Re-export login helpers under manja::kite::login when the
      webdriver-login feature is enabled.
    • Keep WebDriver/TOTP dependencies out of minimal HTTP-only builds.

PH2-T08 – Relocate and adjust tests across crates

  • Introduced facade-level integration tests under manja/tests:
    • facade_http.rs – exercises the ManjaClient facade against mocked
      HTTP endpoints for margins and charges, using shared fixtures from
      kiteconnect-mocks.
    • facade_ticker.rs – ensures that ticker types and URI construction are
      accessible via the facade and remain consistent with the underlying
      manja-ticker implementation.
  • Added and/or updated HTTP-specific test utilities in manja-http (e.g.,
    test_utils.rs) to localize HTTP test harness code to the HTTP crate.
  • Ensured tests use manja-core models and errors from their new locations,
    aligning the test suite with the new crate boundaries.

PH2-T09 – Adjust examples to use workspace and facade

  • Updated manja/examples/* to import from the manja facade crate rather
    than internal modules:
    • basic_http.rs – demonstrates login and basic user/margins flows via
      ManjaClient.
    • quotes.rs and ticker.rs – demonstrate market data and ticker usage
      through facade-level APIs.
  • Ensured the commands in README.md use cargo run -p manja with the
    appropriate examples and features, reflecting the workspace layout.

PH2-T10 – Document workspace architecture

  • Added ARCHITECTURE.md at the workspace root:
    • Documents each crate and its responsibilities:
      • manja – facade crate and example binary.
      • manja-core – shared models, errors, and traits.
      • manja-http – HTTP client and API groups.
      • manja-ticker – WebSocket ticker runtime.
      • manja-extras – WebDriver/TOTP login helpers.
    • Explains when to depend on the manja facade vs. the internal crates
      (manja-core, manja-http, manja-ticker, manja-extras).
    • Describes how feature flags (websocket, webdriver-login, backoff,
      dotenv-config) map onto the workspace crates.
  • Updated the introduction in README.md to:
    • Mention the multi-crate workspace architecture.
    • Point readers to ARCHITECTURE.md for a detailed overview of crate
      boundaries and dependency patterns.

PH2-T11 – Update CI to match workspace + feature matrix

  • Updated .github/workflows/ci.yml to run builds and tests against the
    manja crate within the workspace for each matrix profile:
    • cargo build -p manja ${{ matrix.profile['cargo-flags'] }}
    • cargo test -p manja ${{ matrix.profile['cargo-flags'] }} -- --nocapture
    • cargo test -p manja ${{ matrix.profile['cargo-flags'] }} --doc
  • Preserved the existing feature matrix:
    • default
    • no-default-features
    • http-websocket (--no-default-features --features websocket)
    • http-webdriver-login (--no-default-features --features webdriver-login)
  • Ensured CI remains aligned with the new workspace structure and verifies
    the facade crate under multiple feature combinations.

Public API & Migration Notes

  • The primary entrypoint remains manja::ManjaClient, with the same high-
    level usage as in Phase 1.
  • Existing users relying on:
    • use manja::ManjaClient;
    • use manja::{KiteApiResponse, UserProfile, UserSession, ...};
      should not require code changes; the facade and key types are re-exported
      from their new crate locations.
  • Advanced users can now:
    • Depend on manja-core for shared models and errors only.
    • Depend on manja-http for lower-level HTTP client access.
    • Depend on manja-ticker or manja-extras directly when they want to
      integrate the ticker or WebDriver login flows into custom runtimes.

Testing & CI

  • Tests:
    • cargo test -p manja (with default features) exercises the facade and
      integration tests.
    • HTTP-specific tests live in manja-http and can be run via
      cargo test -p manja-http.
    • Ticker and extras code paths are covered via a combination of facade
      tests and crate-local tests.
  • CI:
    • GitHub Actions workflow runs build, tests, and doctests for manja
      under multiple feature profiles, ensuring the facade crate remains
      healthy across configurations.

Context:

- Phase: PH2
- Task: PH2-T01 Initialize Cargo workspace and member crates

Changes:

- Converted root Cargo.toml into a workspace manifest with members manja,
  manja-core, manja-http, manja-ticker, and manja-extras
- Moved the existing crate configuration from the root Cargo.toml into
  manja/Cargo.toml, preserving package metadata, dependencies, and features
- Relocated the original crate sources from src/, tests/, and examples/
  into manja/src/, manja/tests/, and manja/examples/
- Added stub crates manja-core, manja-http, manja-ticker, and manja-extras
  with minimal Cargo.toml metadata and placeholder src/lib.rs modules

Notes:

- Tests: cargo build --all
- Follow-up: wire manja-core, manja-http, manja-ticker, and manja-extras
  into the main crate in PH2-T02–PH2-T07
Context:

- Phase: PH2
- Task: PH2-T02 Move shared types and errors into manja-core

Changes:

- Added serde/serde_json/chrono/secrecy dependencies and real module roots
  to manja-core for pure models and API-level errors
- Moved Kite HTTP models from manja into manja-core::models and re-exported
  them via the manja kite::connect::models facade
- Extracted KiteApiError and KiteApiException into manja-core::error and
  updated ManjaError to wrap the core error types
- Wired the manja crate to depend on manja-core while preserving the
  existing public re-exports at the manja crate root
- Introduced a resolve_fixture_path helper for tests and updated market and
  session tests to load fixtures correctly in a workspace layout
- Ensured workspace builds and tests succeed with cargo build --all and
  cargo test -p manja

Notes:

- Tests: cargo build --all; cargo test -p manja
- Follow-up: wire manja-http, manja-ticker, and manja-extras to consume
  manja-core types in PH2-T04–PH2-T07
Context:

- Phase: PH2
- Task: PH2-T03 Define reusable traits in manja-core

Changes:

- Added transport-agnostic config/auth/login traits in manja-core/src/traits.rs
- Exposed new core traits module via manja-core/src/lib.rs
- Implemented CoreApiEndpoints and CoreCredentials for Config in manja/src/kite/connect/config.rs
- Updated KiteAuth HeaderMap impl in manja/src/kite/traits.rs to use DefaultKiteAuth from manja-core
- Imported CoreAuth into manja/src/kite/traits.rs so DefaultKiteAuth methods are in scope

Notes:

- Tests: cargo build --all
Context:

- Phase: PH2
- Task: PH2-T04 Move HTTP client and API groups into manja-http

Changes:

- Implemented manja-http crate HTTP config and credentials using manja-core
  traits (manja-http/src/config.rs, manja-http/src/credentials.rs)
- Added dedicated HTTP error type and result alias that wrap
  manja-core::error::KiteApiError (manja-http/src/error.rs)
- Ported HTTPClient implementation to manja-http, using reqwest, optional backoff,
  and manja-core models for responses (manja-http/src/client.rs)
- Implemented HTTP API groups (session, user, orders, portfolio, market, margins,
  charges) against HTTPClient and manja-core types (manja-http/src/api/*.rs)
- Added checksum helper and CSV parsing utilities plus wired new modules and
  dependencies into manja-http (manja-http/src/utils.rs, manja-http/Cargo.toml,
  manja-http/src/lib.rs)

Notes:

- Tests: cargo build -p manja-http && cargo build --all
- Follow-up: PH2-T05 should rewire manja::ManjaClient and kite::connect to depend
  on manja-http and gradually retire the old in-crate HTTP client and API modules
Context:

- Phase: PH2
- Task: PH2-T05 Rewire ManjaClient to use manja-http

Changes:

- Added manja-http as a workspace dependency in manja/Cargo.toml so
  the facade crate can share the HTTP transport layer
- Refactored manja::kite::connect::client::HTTPClient into a thin
  wrapper over manja_http::HTTPClient, mapping manja_http::error::Error
  into ManjaError to preserve the existing error surface
- Kept the existing Config, KiteCredentials, and UserSession types
  in manja by adding helpers to convert between facade config and
  manja-http config (http_config_from_manja_config,
  config_from_http_config)
- Left the ManjaClient facade API unchanged while ensuring its HTTP
  behavior now flows through the wrapped transport client backed by
  manja-http
- Verified the refactor by running cargo check -p manja and
  cargo test -p manja to ensure the crate still builds and tests pass

Notes:

- Tests: cargo check -p manja; cargo test -p manja (default features)
- Design: chose a wrapper-based approach so existing public types and
  imports (kite::connect::client::HTTPClient,
  crate::kite::error::Result) remain stable while HTTP behavior is
  delegated to the manja-http crate
Context:

- Phase: PH2
- Task: PH2-T06 Move WebSocket ticker into manja-ticker

Changes:

- Added ticker client, stream, and models modules to
  manja-ticker/src/{client.rs,stream.rs,models/**} and wired crate
  exports via manja-ticker/src/lib.rs
- Declared WebSocket runtime dependencies (tokio-tungstenite,
  tungstenite, stubborn-io, tracing, serde, serde_json,
  secrecy, futures-util, manja-core) in
  manja-ticker/Cargo.toml and integrated UserSession from
  manja_core::models in manja-ticker/src/stream.rs
- Updated manja/Cargo.toml to depend on manja-ticker as an
  optional crate and changed the websocket feature to enable
  dep:manja-ticker instead of direct WebSocket dependencies
- Replaced the in-crate ticker implementation under
  manja/src/kite/ticker/** with a thin facade in
  manja/src/kite/ticker/mod.rs that re-exports
  KiteStreamCredentials, StreamState, Mode, TickerRequest,
  TickerStream, and WebSocketClient from manja-ticker
- Adjusted manja/src/main.rs to log ticker StreamState using
  to_uri() and removed the direct tungstenite import now provided
  via manja-ticker
- Preserved the public ticker API used by
  manja/examples/ticker.rs by keeping the
  `manja::kite::ticker::{KiteStreamCredentials, Mode, StreamState,

Notes:

- Tests: cargo build --all (default features)
- Follow-up: add focused ticker tests in manja-ticker and update
  docs/examples per PH2-T08/PH2-T09
Context:

- Phase: PH2
- Task: PH2-T07 Move WebDriver login into manja-extras

Changes:

- Implemented WebDriver/TOTP-based login runtime in manja-extras
  (login::{chrome, flow, totp, error}) and re-exported helpers from
  manja-extras/src/lib.rs
- Switched manja’s webdriver-login feature to depend on optional
  manja-extras instead of directly on fantoccini, totp-rs, and base32
- Refactored manja::kite::login::{browser_login_flow, launch_browser,
  generate_totp} into thin facades that delegate to manja-extras using
  manja-core::traits::CoreConfig
- Updated ManjaError to decouple from fantoccini types and added an explicit
  From<manja_extras::login::LoginError> mapping for WebDriver/TOTP failures
- Added README “Advanced WebDriver login usage” section and extended
  manja-extras crate-level docs to show how to depend on and call manja-extras
  directly

Notes:

- Tests: cargo check --workspace
- Design: manja-extras::browser_login_flow now takes C: CoreConfig + Send,
  with a boxed KiteConfig adapter in manja to keep existing public signatures
  while satisfying Send bounds for KiteLoginFlow
Context:

- Phase: PH2
- Task: PH2-T08 Relocate and Adjust Tests Across Crates

Changes:

- Moved HTTP unit tests and fixture helpers from manja/src/kite/connect/**
  into manja-http/src/api/** and manja-http/src/test_utils.rs
- Added mockito as a dev-dependency in manja-http and gated its test_utils
  module behind #[cfg(test)] for crate-local test usage
- Added ticker unit tests in manja-ticker for TickerRequest JSON shape and
  StreamState/SubscriptionStream URI and message generation
- Introduced facade-level integration tests in manja/tests/facade_http.rs and
  manja/tests/facade_ticker.rs plus shared helpers in manja/tests/support.rs
- Removed legacy HTTP test modules and test_utils from the manja crate so HTTP
  behavior is unit-tested only in manja-http and facade tests use ManjaClient
- Verified workspace test coherence so cargo test --all runs HTTP, ticker, and
  facade tests without duplication

Notes:

- Tests:
  - cargo test -p manja-http
  - cargo test -p manja-ticker
  - cargo test -p manja
  - cargo test --all
- User/profile and margins fixtures remain missing; corresponding user API
  tests are kept commented in manja-http::api::user for future re-enabling
Context:

- Phase: PH2
- Task: PH2-T09 Adjust examples to use workspace and facade

Changes:

- Updated ticker example fallback message to use
  cargo run -p manja --example ticker --features websocket
- Confirmed all examples import only from the manja facade crate and
  not internal workspace crates
- Extended README with a workspace-aware Examples section showing how
  to run basic_http, quotes, and ticker from the workspace root

Notes:

- Tests: cargo check -p manja --examples
Context:

- Phase: PH2
- Task: PH2-T10 Document workspace architecture

Changes:

- Added ARCHITECTURE.md describing workspace crates, responsibilities, and
  feature layering across manja, manja-core, manja-http, manja-ticker, and
  manja-extras
- Updated README.md introduction to mention the multi-crate workspace and
  point readers to ARCHITECTURE.md for detailed architecture docs
- Updated .gitignore to ignore a workspace-level main.rs helper binary

Notes:

- Tests: not run (documentation-only and ignore-rule changes)
Context:

- Phase: PH2
- Task: PH2-T11 Update CI for manja workspace

Changes:

- Updated .github/workflows/ci.yml to run cargo build against the manja
  crate using cargo build -p manja for all matrix profiles
- Updated CI test step to run cargo test -p manja with the existing
  feature matrix (default, no-default-features, websocket, webdriver-login)
- Updated CI doctest step to run cargo test -p manja --doc so docs are
  validated for each feature profile

Notes:

- Tests: workflow not executed locally; change scopes existing CI commands
  to the manja package to match the multi-crate workspace layout
Context:

- Phase: PH2
- Task: PH2-T11 Update CI for manja workspace

Changes:

- Extended .github/workflows/ci.yml feature matrix to add http-backoff
  (HTTP + backoff only) profile
- Added http-websocket-backoff profile to validate ticker + backoff
  combination without webdriver or dotenv
- Added http-webdriver-login-backoff profile to validate webdriver login +
  backoff combination without websocket or dotenv
- Kept build, unit/integration tests, and doctests running for each new
  profile against the manja crate

Notes:

- Tests: workflow not executed locally; changes only adjust CI matrix
  configuration and reuse existing steps
Context:

- Phase: PH2
- Task: PH2-T08 Relocate and adjust tests across crates

Changes:

- Updated manja/tests/facade_ticker.rs to be compiled only when the
  websocket feature is enabled via a crate-level `#![cfg(feature =
- Ensured ticker facade tests no longer reference the optional
  manja-ticker crate in HTTP-only and non-websocket CI profiles
- Verified cargo test -p manja across multiple feature profiles
  (no-default-features, backoff, websocket, websocket+backoff,
  webdriver-login, webdriver-login+backoff) completes successfully

Notes:

- Tests: cargo test -p manja with the above feature combinations ran
  locally and passed; remaining warnings are unrelated (unused code)
@saxena-dev saxena-dev merged commit 53193d3 into develop Dec 9, 2025
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants