usecases

package module
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2026 License: MIT Imports: 21 Imported by: 0

README

kite-mcp-usecases

Go Reference

Application use case layer for the algo2go ecosystem. Implements write-side CQRS commands + read-side queries across all major trading domains: orders (place/modify/cancel/close), portfolio (holdings, P&L, dividends, sectors, returns), alerts (price, composite, native), oauth bridge, sessions, tickers, options strategy, paper trading, family accounts, data export, telegram events, watchlists, consent, observability, plus the Saga + Ports contracts.

Used by Sundeepg98/kite-mcp-server as the contract layer between the kc/manager state machine and the MCP tool layer; every user-visible MCP tool dispatches through one or more use cases here.

Why a separate module?

The use case layer is the most user-visible surface of the trading-platform domain — externalizing it completes the "ports & adapters" architecture migration. Hosting as its own module:

  • Centralizes write-side commands + read-side queries
  • Lets command/query signatures version independently from the monolith
  • Decouples saga orchestration from any one runtime
  • Provides a stable contract for any consumer wiring algo2go trading domain primitives (alerts/orders/portfolio/etc.) into a custom MCP server, REST API, or direct embedding

Stability promise

v0.x — unstable. Pin v0.1.0 deliberately.

Install

go get github.com/algo2go/kite-mcp-usecases@v0.1.0

Public API (high-level)

  • Order use cases — PlaceOrder, ModifyOrder, CancelOrder, ClosePosition, CloseAllPositions, ConvertPosition, GetOrders, pretrade check
  • Portfolio use cases — GetPortfolio, P&L, options strategy
  • Alert use cases — CreateAlert, CreateCompositeAlert, TrailingStop, NativeAlert
  • Account use cases — Account, Admin, Family, OAuthBridge, Session, Setup, Consent, DataExport, Margin
  • Domain use cases — Watchlist, GTT, MF (mutual funds), Ticker, Telegram events, Widget, Native alerts
  • Paper trading — virtual portfolio mode use cases
  • Cross-cutting — Observability, Pretrade, Saga, Ports contracts

Dependencies (11 algo2go modules)

  • github.com/algo2go/kite-mcp-alerts v0.1.0
  • github.com/algo2go/kite-mcp-broker v0.1.0
  • github.com/algo2go/kite-mcp-cqrs v0.1.0
  • github.com/algo2go/kite-mcp-domain v0.1.0
  • github.com/algo2go/kite-mcp-eventsourcing v0.1.0
  • github.com/algo2go/kite-mcp-logger v0.1.0
  • github.com/algo2go/kite-mcp-money v0.1.0
  • github.com/algo2go/kite-mcp-riskguard v0.1.0
  • github.com/algo2go/kite-mcp-ticker v0.1.0
  • github.com/algo2go/kite-mcp-users v0.1.0
  • github.com/algo2go/kite-mcp-watchlist v0.1.0
  • github.com/stretchr/testify v1.10.0

All algo2go deps published; no upstream replace directives needed.

Reference consumer

Sundeepg98/kite-mcp-server — consumed across 38 .go files: kc/manager_, kc/ops/payoff.go, app/, mcp/* (admin, analytics, common, helpers, paper, plugin widgets, portfolio, trade, watchlist, tax tools, tools_ext_apps).

License

MIT — see LICENSE.

Authors

Original design: Sundeepg98 (Zerodha Tech). Multi-module promotion (2026-05-10): algo2go contributors.

Documentation

Overview

Package usecases contains application use cases that orchestrate domain logic, infrastructure services, and cross-cutting concerns (riskguard, events).

Each use case is a single-purpose struct with an Execute method, following Clean Architecture principles. Use cases depend on interfaces, not concrete implementations, making them fully testable with mocks.

Index

Constants

View Source
const (
	UserStatusSuspended  = "suspended"
	UserStatusOffboarded = "offboarded"
)

User-status sentinels for the bridge; mirrors the kc/users package constants (Suspended/Offboarded). Keeping them as exported strings here means usecases doesn't import kc/users.

View Source
const (
	RegistryStatusActive          = "active"
	RegistryStatusReplaced        = "replaced"
	RegistrySourceSelfProvisioned = "self-provisioned"
)

Registry status / source sentinels mirrored from kc/registry to keep usecases free of an import on that package. Values must match kc/registry/store.go's StatusActive / StatusReplaced / SourceSelfProvisioned constants exactly — they're persisted to SQLite and consumed by registry queries.

View Source
const DataExportRetention = 5 * 365 * 24 * time.Hour

DataExportRetention is the lookback window applied to time-bounded tables (tool_calls, domain_events). 5 years matches the most conservative DPDP retention guidance for trading-related records.

View Source
const RegistrySourceAdmin = "admin"

RegistrySourceAdmin is the source label for entries created by admins from the ops dashboard (vs self-provisioned via OAuth callback). Mirrors kc/registry.SourceAdmin so usecases stays independent.

Variables

View Source
var ErrUserOffboarded = errors.New("user account has been offboarded")

ErrUserOffboarded is returned by ProvisionUserOnLoginUseCase when the target email is offboarded — terminal status, distinct from suspended (suspended can be re-activated by an admin).

View Source
var ErrUserSuspended = errors.New("user account is suspended")

ErrUserSuspended is returned by ProvisionUserOnLoginUseCase when the target email already has the suspended status set in the user store. Callers (the OAuth-callback handler) should fail the login and emit a 403 to the client.

Functions

func RegisterOAuthClientHandlers

func RegisterOAuthClientHandlers(
	bus *cqrs.InMemoryBus,
	clientStore func() OAuthClientStore,
	logger *slog.Logger,
	errPrefix string,
) error

RegisterOAuthClientHandlers wires the SaveOAuthClient + DeleteOAuthClient command handlers onto the given bus. The handler bodies are thin type-assert + use-case-construct + dispatch sequences identical in shape to the production registration in kc/manager_commands_oauth.go and the test-mode mirror in app/adapters_local_bus.go (which had two near-identical 30-LOC blocks before this F6 close-out extracted the shared shape here).

Parameters:

  • bus: the *cqrs.InMemoryBus to register on (Manager-bound in production via *kc.Manager.commandBus; fresh in-process bus in the test-mode app/adapters_local_bus.go local pattern). Concrete pointer type rather than the cqrs.CommandBus interface because Register is implementation-only (the interface exposes only Dispatch / DispatchWithResult; registration is a wiring concern, not a runtime contract).
  • clientStore: thunk returning the OAuthClientStore implementation to bind. Thunked rather than passed directly so callers can defer the AlertDB read to dispatch time (matches the existing nil-safe pattern in both call sites — when AlertDB is nil, the use case no-ops rather than failing the registration).
  • logger: bound into each constructed use case via logport.NewSlog inside NewSaveOAuthClientUseCase / NewDeleteOAuthClientUseCase. Should be the same logger production-bus consumers use to keep audit trails uniform.
  • errPrefix: prepended to the type-assertion error message ("cqrs" or "local bus" — preserved verbatim from each callsite's existing format string).

Returns the FIRST registration error encountered; bus.Register only fails on duplicate type registration, so in practice this returns nil for fresh buses. Callers in test-mode local-bus contexts panic on the returned error (matching the pre-F6 panic-vs-return semantics — duplicate Register is a programmer error, not a runtime failure).

Phase B/D F6 close: extracted from kc/manager_commands_oauth.go (registerOAuthBridgeCommands lines 92-121) and app/adapters_local_bus .go (newLocalOAuthClientBus lines 144-175). Both pre-extraction blocks had byte-different but structurally-identical type-assert+construct+dispatch sequences; this helper is the canonical shape consumed from both sites.

func RunSaga

func RunSaga(ctx context.Context, logger *slog.Logger, name string, steps []SagaStep) error

RunSaga executes the steps in order. On the first non-ContinueOnError failure, it runs Compensate on every prior completed step in reverse order, then returns a *SagaError. If all steps run to completion, returns nil.

The logger MAY be nil; nil-logger is treated as a no-op for diagnostic log lines. The signature accepts *slog.Logger for caller compatibility and converts via logport.NewSlog at the boundary so internal log statements use the kc/logger.Logger port. The context is threaded into both Action and Compensate so cancellation propagates to in-flight steps and to compensations.

Compensation runs in REVERSE order: step N-1, N-2, ..., 0. This matches LIFO undo semantics — the most recent change is undone first.

Types

type AccountDependencies

type AccountDependencies struct {
	CredentialStore CredentialUpdater
	TokenStore      TokenStore
	AlertDeleter    AlertDeleter
	WatchlistStore  WatchlistStore
	TrailingStops   TrailingStopManager
	PaperEngine     PaperEngine
	UserStore       AdminUserStore
	Sessions        SessionTerminator
}

AccountDependencies groups stores needed for account deletion.

type AddToWatchlistUseCase

type AddToWatchlistUseCase struct {
	// contains filtered or unexported fields
}

AddToWatchlistUseCase adds an instrument to a watchlist.

func NewAddToWatchlistUseCase

func NewAddToWatchlistUseCase(store WatchlistStore, logger *slog.Logger) *AddToWatchlistUseCase

NewAddToWatchlistUseCase creates an AddToWatchlistUseCase with dependencies injected.

func (*AddToWatchlistUseCase) Execute

func (uc *AddToWatchlistUseCase) Execute(ctx context.Context, cmd cqrs.AddToWatchlistCommand) error

Execute adds an instrument to a watchlist.

func (*AddToWatchlistUseCase) SetEventDispatcher

func (uc *AddToWatchlistUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the domain event dispatcher for typed WatchlistItemAddedEvent emission. See CreateWatchlistUseCase SetEventDispatcher for the dispatch-vs-audit rationale. Nil-safe.

func (*AddToWatchlistUseCase) SetEventStore

func (uc *AddToWatchlistUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. Phase C ES.

type AdminActivateUserUseCase

type AdminActivateUserUseCase struct {
	// contains filtered or unexported fields
}

AdminActivateUserUseCase reactivates a user account.

func NewAdminActivateUserUseCase

func NewAdminActivateUserUseCase(store AdminUserWriter, logger *slog.Logger) *AdminActivateUserUseCase

NewAdminActivateUserUseCase creates an AdminActivateUserUseCase with dependencies injected.

func (*AdminActivateUserUseCase) Execute

func (uc *AdminActivateUserUseCase) Execute(ctx context.Context, cmd cqrs.AdminActivateUserCommand) error

Execute activates a user.

type AdminChangeRoleResult

type AdminChangeRoleResult struct {
	Email   string `json:"email"`
	OldRole string `json:"old_role"`
	NewRole string `json:"new_role"`
}

AdminChangeRoleResult holds the role change result.

type AdminChangeRoleUseCase

type AdminChangeRoleUseCase struct {
	// contains filtered or unexported fields
}

AdminChangeRoleUseCase changes a user's role.

func NewAdminChangeRoleUseCase

func NewAdminChangeRoleUseCase(store AdminUserStore, logger *slog.Logger) *AdminChangeRoleUseCase

NewAdminChangeRoleUseCase creates an AdminChangeRoleUseCase with dependencies injected.

func (*AdminChangeRoleUseCase) Execute

func (uc *AdminChangeRoleUseCase) Execute(ctx context.Context, cmd cqrs.AdminChangeRoleCommand) (*AdminChangeRoleResult, error)

Execute changes a user's role.

type AdminDeleteRegistryUseCase

type AdminDeleteRegistryUseCase struct {
	// contains filtered or unexported fields
}

AdminDeleteRegistryUseCase removes a registry entry.

func NewAdminDeleteRegistryUseCase

func NewAdminDeleteRegistryUseCase(r RegistryAdminWriter, logger *slog.Logger) *AdminDeleteRegistryUseCase

NewAdminDeleteRegistryUseCase builds the use case.

func (*AdminDeleteRegistryUseCase) Execute

func (uc *AdminDeleteRegistryUseCase) Execute(_ context.Context, cmd cqrs.AdminDeleteRegistryCommand) error

Execute runs the use case.

type AdminFreezeGlobalUseCase

type AdminFreezeGlobalUseCase struct {
	// contains filtered or unexported fields
}

AdminFreezeGlobalUseCase freezes all trading globally.

func NewAdminFreezeGlobalUseCase

func NewAdminFreezeGlobalUseCase(rg RiskGuardService, logger *slog.Logger) *AdminFreezeGlobalUseCase

NewAdminFreezeGlobalUseCase creates an AdminFreezeGlobalUseCase with dependencies injected.

func (*AdminFreezeGlobalUseCase) Execute

func (uc *AdminFreezeGlobalUseCase) Execute(ctx context.Context, cmd cqrs.AdminFreezeGlobalCommand) error

Execute freezes all trading globally.

type AdminFreezeUserUseCase

type AdminFreezeUserUseCase struct {
	// contains filtered or unexported fields
}

AdminFreezeUserUseCase freezes a user's trading.

func NewAdminFreezeUserUseCase

func NewAdminFreezeUserUseCase(rg RiskGuardService, logger *slog.Logger) *AdminFreezeUserUseCase

NewAdminFreezeUserUseCase creates an AdminFreezeUserUseCase with dependencies injected.

func (*AdminFreezeUserUseCase) Execute

func (uc *AdminFreezeUserUseCase) Execute(ctx context.Context, cmd cqrs.AdminFreezeUserCommand) error

Execute freezes a user's trading.

type AdminGetRiskStatusResult

type AdminGetRiskStatusResult struct {
	TargetEmail     string               `json:"target_email"`
	GloballyFrozen  bool                 `json:"globally_frozen"`
	UserStatus      riskguard.UserStatus `json:"user_status"`
	EffectiveLimits riskguard.UserLimits `json:"effective_limits"`
	OrderHeadroom   float64              `json:"order_headroom"`
}

AdminGetRiskStatusResult holds a user's risk status.

type AdminGetRiskStatusUseCase

type AdminGetRiskStatusUseCase struct {
	// contains filtered or unexported fields
}

AdminGetRiskStatusUseCase retrieves a user's risk status.

func NewAdminGetRiskStatusUseCase

func NewAdminGetRiskStatusUseCase(rg RiskGuardService, logger *slog.Logger) *AdminGetRiskStatusUseCase

NewAdminGetRiskStatusUseCase creates an AdminGetRiskStatusUseCase with dependencies injected.

func (*AdminGetRiskStatusUseCase) Execute

func (uc *AdminGetRiskStatusUseCase) Execute(ctx context.Context, query cqrs.AdminGetRiskStatusQuery) (*AdminGetRiskStatusResult, error)

Execute retrieves a user's risk status.

type AdminGetUserResult

type AdminGetUserResult struct {
	User            *users.User           `json:"user"`
	RiskStatus      *riskguard.UserStatus `json:"risk_status,omitempty"`
	EffectiveLimits *riskguard.UserLimits `json:"effective_limits,omitempty"`
}

AdminGetUserResult holds detailed user information.

type AdminGetUserUseCase

type AdminGetUserUseCase struct {
	// contains filtered or unexported fields
}

AdminGetUserUseCase retrieves detailed user information.

func NewAdminGetUserUseCase

func NewAdminGetUserUseCase(store AdminUserReader, rg RiskGuardService, logger *slog.Logger) *AdminGetUserUseCase

NewAdminGetUserUseCase creates an AdminGetUserUseCase with dependencies injected.

func (*AdminGetUserUseCase) Execute

func (uc *AdminGetUserUseCase) Execute(ctx context.Context, query cqrs.AdminGetUserQuery) (*AdminGetUserResult, error)

Execute retrieves a user's detailed information.

type AdminInviteFamilyMemberResult

type AdminInviteFamilyMemberResult struct {
	InvitationID string    `json:"invitation_id"`
	InvitedEmail string    `json:"invited_email"`
	ExpiresAt    time.Time `json:"expires_at"`
	SlotsUsed    int       `json:"slots_used"`
	SlotsMax     int       `json:"slots_max"`
}

AdminInviteFamilyMemberResult holds the outcome of a successful invite.

type AdminInviteFamilyMemberUseCase

type AdminInviteFamilyMemberUseCase struct {
	// contains filtered or unexported fields
}

AdminInviteFamilyMemberUseCase creates a family invitation after enforcing slot limits via FamilyService.CanInvite.

func NewAdminInviteFamilyMemberUseCase

func NewAdminInviteFamilyMemberUseCase(
	family FamilyProvider,
	invitations FamilyInvitationWriter,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *AdminInviteFamilyMemberUseCase

NewAdminInviteFamilyMemberUseCase creates an AdminInviteFamilyMemberUseCase.

func (*AdminInviteFamilyMemberUseCase) Execute

func (uc *AdminInviteFamilyMemberUseCase) Execute(ctx context.Context, cmd cqrs.AdminInviteFamilyMemberCommand) (*AdminInviteFamilyMemberResult, error)

Execute creates a pending family invitation after slot + duplicate checks.

type AdminListFamilyResult

type AdminListFamilyResult struct {
	AdminEmail  string                  `json:"admin_email"`
	MaxUsers    int                     `json:"max_users"`
	Total       int                     `json:"total"`
	From        int                     `json:"from"`
	Limit       int                     `json:"limit"`
	MemberCount int                     `json:"member_count"`
	Members     []FamilyMemberEntry     `json:"members"`
	Pending     []FamilyInvitationEntry `json:"pending"`
}

AdminListFamilyResult holds the paginated family listing + pending invites.

type AdminListFamilyUseCase

type AdminListFamilyUseCase struct {
	// contains filtered or unexported fields
}

AdminListFamilyUseCase returns the admin's family members and pending invitations.

func NewAdminListFamilyUseCase

func NewAdminListFamilyUseCase(
	family FamilyProvider,
	invitations FamilyInvitationReader,
	logger *slog.Logger,
) *AdminListFamilyUseCase

NewAdminListFamilyUseCase creates an AdminListFamilyUseCase.

func (*AdminListFamilyUseCase) Execute

func (uc *AdminListFamilyUseCase) Execute(ctx context.Context, query cqrs.AdminListFamilyQuery) (*AdminListFamilyResult, error)

Execute lists family members for the admin.

type AdminListUsersResult

type AdminListUsersResult struct {
	Total int           `json:"total"`
	From  int           `json:"from"`
	Limit int           `json:"limit"`
	Users []*users.User `json:"users"`
}

AdminListUsersResult holds the paginated user list.

type AdminListUsersUseCase

type AdminListUsersUseCase struct {
	// contains filtered or unexported fields
}

AdminListUsersUseCase retrieves a paginated list of users.

func NewAdminListUsersUseCase

func NewAdminListUsersUseCase(store AdminUserReader, logger *slog.Logger) *AdminListUsersUseCase

NewAdminListUsersUseCase creates an AdminListUsersUseCase with dependencies injected.

func (*AdminListUsersUseCase) Execute

func (uc *AdminListUsersUseCase) Execute(ctx context.Context, query cqrs.AdminListUsersQuery) (*AdminListUsersResult, error)

Execute retrieves a paginated list of users.

type AdminRegisterAppUseCase

type AdminRegisterAppUseCase struct {
	// contains filtered or unexported fields
}

AdminRegisterAppUseCase persists a new key-registry entry created from the admin dashboard.

func NewAdminRegisterAppUseCase

func NewAdminRegisterAppUseCase(r RegistryAdminWriter, logger *slog.Logger) *AdminRegisterAppUseCase

NewAdminRegisterAppUseCase builds the use case.

func (*AdminRegisterAppUseCase) Execute

func (uc *AdminRegisterAppUseCase) Execute(_ context.Context, cmd cqrs.AdminRegisterAppCommand) error

Execute runs the use case.

type AdminRemoveFamilyMemberResult

type AdminRemoveFamilyMemberResult struct {
	RemovedEmail string `json:"removed_email"`
}

AdminRemoveFamilyMemberResult holds the outcome of a remove call.

type AdminRemoveFamilyMemberUseCase

type AdminRemoveFamilyMemberUseCase struct {
	// contains filtered or unexported fields
}

AdminRemoveFamilyMemberUseCase unlinks a family member via FamilyService.

func NewAdminRemoveFamilyMemberUseCase

func NewAdminRemoveFamilyMemberUseCase(
	family FamilyProvider,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *AdminRemoveFamilyMemberUseCase

NewAdminRemoveFamilyMemberUseCase creates an AdminRemoveFamilyMemberUseCase.

func (*AdminRemoveFamilyMemberUseCase) Execute

func (uc *AdminRemoveFamilyMemberUseCase) Execute(ctx context.Context, cmd cqrs.AdminRemoveFamilyMemberCommand) (*AdminRemoveFamilyMemberResult, error)

Execute unlinks a family member from the admin.

type AdminSuspendUserResult

type AdminSuspendUserResult struct {
	Status             string `json:"status"`
	Email              string `json:"email"`
	SessionsTerminated int    `json:"sessions_terminated"`
}

AdminSuspendUserResult holds the suspension result.

type AdminSuspendUserUseCase

type AdminSuspendUserUseCase struct {
	// contains filtered or unexported fields
}

AdminSuspendUserUseCase suspends a user account.

func NewAdminSuspendUserUseCase

func NewAdminSuspendUserUseCase(
	store AdminUserStore,
	rg RiskGuardService,
	sessions SessionTerminator,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *AdminSuspendUserUseCase

NewAdminSuspendUserUseCase creates an AdminSuspendUserUseCase with dependencies injected.

func (*AdminSuspendUserUseCase) Execute

func (uc *AdminSuspendUserUseCase) Execute(ctx context.Context, cmd cqrs.AdminSuspendUserCommand) (*AdminSuspendUserResult, error)

Execute suspends a user.

type AdminUnfreezeGlobalUseCase

type AdminUnfreezeGlobalUseCase struct {
	// contains filtered or unexported fields
}

AdminUnfreezeGlobalUseCase unfreezes global trading.

func NewAdminUnfreezeGlobalUseCase

func NewAdminUnfreezeGlobalUseCase(rg RiskGuardService, logger *slog.Logger) *AdminUnfreezeGlobalUseCase

NewAdminUnfreezeGlobalUseCase creates an AdminUnfreezeGlobalUseCase with dependencies injected.

func (*AdminUnfreezeGlobalUseCase) Execute

func (uc *AdminUnfreezeGlobalUseCase) Execute(ctx context.Context, cmd cqrs.AdminUnfreezeGlobalCommand) error

Execute unfreezes global trading.

type AdminUnfreezeUserUseCase

type AdminUnfreezeUserUseCase struct {
	// contains filtered or unexported fields
}

AdminUnfreezeUserUseCase unfreezes a user's trading.

func NewAdminUnfreezeUserUseCase

func NewAdminUnfreezeUserUseCase(rg RiskGuardService, logger *slog.Logger) *AdminUnfreezeUserUseCase

NewAdminUnfreezeUserUseCase creates an AdminUnfreezeUserUseCase with dependencies injected.

func (*AdminUnfreezeUserUseCase) Execute

func (uc *AdminUnfreezeUserUseCase) Execute(ctx context.Context, cmd cqrs.AdminUnfreezeUserCommand) error

Execute unfreezes a user's trading.

type AdminUpdateRegistryUseCase

type AdminUpdateRegistryUseCase struct {
	// contains filtered or unexported fields
}

AdminUpdateRegistryUseCase mutates an existing registry entry's assignment, label, or status.

func NewAdminUpdateRegistryUseCase

func NewAdminUpdateRegistryUseCase(r RegistryAdminWriter, logger *slog.Logger) *AdminUpdateRegistryUseCase

NewAdminUpdateRegistryUseCase builds the use case.

func (*AdminUpdateRegistryUseCase) Execute

func (uc *AdminUpdateRegistryUseCase) Execute(_ context.Context, cmd cqrs.AdminUpdateRegistryCommand) error

Execute runs the use case.

type AdminUserReader

type AdminUserReader interface {
	List() []*users.User
	Get(email string) (*users.User, bool)
	Count() int
}

AdminUserReader provides read-only access to user data (ISP-narrowed).

F2 close-out (Phase B/D): renamed from usecases.UserReader to disambiguate from kc.UserReader (10-method canonical) — the usecases version is a 3-method narrow subset for admin tooling only. Per the redundancy audit's empirical finding: same name, different signatures = future-maintainer confusion. *kc.Manager (and kc.UserStoreInterface implementations) satisfy this narrow port structurally — no adapter layer needed.

UserAuthChecker was deleted (was dead code — declared but never referenced as a field type or function parameter; only embedded in the unused UserStore composite via UserAuthChecker.IsAdmin which no admin use case actually called).

type AdminUserStore

type AdminUserStore interface {
	AdminUserReader
	AdminUserWriter
}

AdminUserStore is the composite interface for admin use cases that need both reads and writes. Prefer AdminUserReader or AdminUserWriter directly when possible (Interface Segregation Principle).

F2 close-out: renamed from usecases.UserStore. UserAuthChecker embedding removed — no admin use case calls IsAdmin/HasPassword/ VerifyPassword on the composite (they route through riskguard / session-svc instead).

type AdminUserWriter

type AdminUserWriter interface {
	UpdateStatus(email, status string) error
	UpdateRole(email, role string) error
	Create(u *users.User) error
}

AdminUserWriter provides write operations on user data (ISP-narrowed).

F2 close-out: renamed from usecases.UserWriter (was a 3-method narrow subset of kc.UserWriter's 8). Same rename rationale as AdminUserReader — disambiguate from the wide kc canonical.

type AlertDeleter

type AlertDeleter interface {
	DeleteByEmail(email string)
}

AlertDeleter abstracts alert deletion for account cleanup.

type AlertExporter

type AlertExporter interface {
	ExportAlerts(email string) ([]any, error)
}

AlertExporter retrieves alerts for the user.

type AlertLister

type AlertLister interface {
	ListActive(email string) []AlertSummary
}

AlertLister abstracts reading active alerts for a user.

type AlertReader

type AlertReader interface {
	List(email string) []*alerts.Alert
	Delete(email, alertID string) error
}

AlertReader abstracts alert read/delete operations for use cases.

type AlertStore

type AlertStore interface {
	Add(email, tradingsymbol, exchange string, instrumentToken uint32, targetPrice float64, direction alerts.Direction) (string, error)
	AddWithReferencePrice(email, tradingsymbol, exchange string, instrumentToken uint32, targetPrice float64, direction alerts.Direction, referencePrice float64) (string, error)
}

AlertStore is the interface needed by CreateAlertUseCase. It matches the subset of kc.AlertStoreInterface used here.

type AlertSummary

type AlertSummary struct {
	Tradingsymbol string
	Exchange      string
	Direction     string
	TargetPrice   float64
	Triggered     bool
}

AlertSummary is a minimal alert representation for the trading context.

type BrokerResolver

type BrokerResolver interface {
	GetBrokerForEmail(email string) (broker.Client, error)
}

BrokerResolver resolves a broker.Client for a given user email.

CONTRACT

Signature:

GetBrokerForEmail(email string) (broker.Client, error)

Return semantics:

(client, nil) — successful resolution. The returned client is
  ready to use. Implementations MAY return the same client
  instance for repeated calls (cache hits) or a fresh instance
  per call (cold construction); use cases MUST NOT assume
  identity across invocations.

(nil, err)   — resolution failed. The error MUST be non-nil and
  the client MUST be nil. Use cases wrap and propagate; they do
  NOT retry at the port level. Common error shapes today:
    - "no Kite access token for {email}" — user not authed
    - broker-factory construction failure
    - downstream credential-store lookup error

Email argument:

The port DOES NOT mandate an email-validity check. Implementations
differ:
  - *kc.SessionService.GetBrokerForEmail (production) — looks up
    the email first in the active-session map (in-memory hit) and
    falls back to credential-store + token-store reconstruction.
    Returns an error when no token is cached for the email.
  - *mcp.sessionBrokerResolver.GetBrokerForEmail (mcp pre-dispatch)
    — IGNORES the email and returns its pre-resolved client. Used
    only by ToolHandler.WithTokenRefresh for the cheap profile-
    probe outside the bus; bus-routed handlers always reach the
    SessionService impl above.
  - test mocks (kc/usecases/mocks_test.go mockBrokerResolver) —
    pass the email through; behaviour follows the test fixture's
    configured client/error pair.

Use cases that need email-shape validation (non-empty, well-formed)
MUST validate before calling GetBrokerForEmail. The port itself
is pass-through.

Thread-safety:

Implementations MUST be safe for concurrent calls from multiple
goroutines. The bus dispatches commands and queries from the MCP
tool layer's per-request goroutines; a use case constructed once
at startup (Wave D's eventual end-state) sees its resolver hit
from N concurrent request paths simultaneously. Production
implementations honor this via internal mutex / sync.Map; test
mocks should as well if exercised under -race.

Lifetime:

The resolver is constructed once per Manager (production) or per
test fixture, and lives for the Manager's lifetime. Use cases
hold the interface value, not a pointer-to-interface — replacing
the resolver implementation requires reconstructing the use case.
(Wave D Slice D-final wires this through Wire/fx providers; until
then, manager_init.go is the construction site.)

"No broker for this ctx" sentinel:

The port has no sentinel — it is email-keyed, not ctx-keyed. After
Wave D Slice D7, ctx no longer carries a per-request broker; every
bus-routed use case receives m.sessionSvc as its BrokerResolver
at construction time and reaches the broker via the SessionService
in-memory active-session map (cost: one in-memory map lookup per
dispatch, ~100 ns; see .research/wave-d-resolver-refactor-plan.md
§5). The previous WithBroker / pinnedBrokerResolver / resolverFromContext
machinery has been removed (commit at end of Wave D Phase 1).

IMPLEMENTATIONS

Production:
  - *kc.SessionService           (kc/session_service.go:541)
  - *mcp.sessionBrokerResolver   (mcp/post_tools.go:19, used by
                                   WithTokenRefresh and similar
                                   pre-dispatch session probes;
                                   out of scope for Wave D Phase 1)

Tests:
  - mockBrokerResolver           (kc/usecases/mocks_test.go:62)
  - brokerResolverTestImpl       (kc/usecases/ports_test.go,
                                   test-only, mirrors the
                                   "ignore-email" shape for
                                   contract coverage)

type BuildOptionsStrategyCommand

type BuildOptionsStrategyCommand struct {
	Email      string
	Strategy   string // bull_call_spread, bear_put_spread, ..., butterfly
	Underlying string // NIFTY, BANKNIFTY, RELIANCE, ...
	Expiry     string // YYYY-MM-DD
	Strike1    float64
	Strike2    float64
	Strike3    float64
	Strike4    float64
	LotSize    int // 0 = auto-detect via OptionInstrumentLookup.DefaultLotSize
	Lots       int // 0 or negative coerced to 1
}

BuildOptionsStrategyCommand is the input shape for the use case. Mirrors the URL/MCP-arg surface of options_payoff_builder.

func ValidateOptionsStrategyCommand

func ValidateOptionsStrategyCommand(cmd BuildOptionsStrategyCommand) (BuildOptionsStrategyCommand, error)

ValidateOptionsStrategyCommand performs pure shape-validation on the command without touching the broker or instruments. Returns the canonical (lowercased / uppercased / trimmed) form of the strategy + underlying so callers can surface arg-shape errors before the session gate. The full Execute path re-validates internally; this is the public entry point for pre-session validation by tool handlers and dashboard endpoints.

type BuildOptionsStrategyUseCase

type BuildOptionsStrategyUseCase struct {
	// contains filtered or unexported fields
}

BuildOptionsStrategyUseCase orchestrates the full options-strategy build: validate input → expand legs by strategy name → resolve instruments → fetch LTPs → compute P&L formulas → return populated StrategyResponse.

Refactor invariant (Phase (a)): output JSON shape matches the pre-refactor mcp/trade strategyResponse so consumers (dashboard payoff page, MCP tool handler) work unchanged after the data-flow swap. The MCP tool handler becomes a thin arg-parse + use-case-call shell; the dashboard endpoint also calls the same use case.

func NewBuildOptionsStrategyUseCase

func NewBuildOptionsStrategyUseCase(resolver BrokerResolver, instruments OptionInstrumentLookup, logger *slog.Logger) *BuildOptionsStrategyUseCase

NewBuildOptionsStrategyUseCase creates a BuildOptionsStrategyUseCase with all dependencies injected. Mirrors the constructor pattern used by other usecases in this package (see queries.go, place_order.go).

func (*BuildOptionsStrategyUseCase) Execute

Execute builds the options strategy and computes its payoff metrics. All input validation, leg expansion, instrument resolution, LTP fetching, and P&L formula application happen here.

type CacheKiteAccessTokenUseCase

type CacheKiteAccessTokenUseCase struct {
	// contains filtered or unexported fields
}

CacheKiteAccessTokenUseCase writes the Kite access token to the per-user token cache. Always lowercases the email.

func NewCacheKiteAccessTokenUseCase

func NewCacheKiteAccessTokenUseCase(t KiteTokenWriter, logger *slog.Logger) *CacheKiteAccessTokenUseCase

NewCacheKiteAccessTokenUseCase builds the use case.

func (*CacheKiteAccessTokenUseCase) Execute

func (uc *CacheKiteAccessTokenUseCase) Execute(_ context.Context, cmd cqrs.CacheKiteAccessTokenCommand) error

Execute runs the use case. A nil tokens writer is a no-op (defensive — production always wires the store).

type CancelMFOrderUseCase

type CancelMFOrderUseCase struct {
	// contains filtered or unexported fields
}

CancelMFOrderUseCase cancels a pending mutual fund order.

func NewCancelMFOrderUseCase

func NewCancelMFOrderUseCase(resolver BrokerResolver, logger *slog.Logger) *CancelMFOrderUseCase

func (*CancelMFOrderUseCase) Execute

func (uc *CancelMFOrderUseCase) Execute(ctx context.Context, cmd cqrs.CancelMFOrderCommand) (broker.MFOrderResponse, error)

func (*CancelMFOrderUseCase) SetEventDispatcher

func (uc *CancelMFOrderUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so broker failures emit MFOrderRejectedEvent. Nil-safe.

func (*CancelMFOrderUseCase) SetEventStore

func (uc *CancelMFOrderUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type CancelMFSIPUseCase

type CancelMFSIPUseCase struct {
	// contains filtered or unexported fields
}

CancelMFSIPUseCase cancels an existing mutual fund SIP.

func NewCancelMFSIPUseCase

func NewCancelMFSIPUseCase(resolver BrokerResolver, logger *slog.Logger) *CancelMFSIPUseCase

func (*CancelMFSIPUseCase) Execute

func (uc *CancelMFSIPUseCase) Execute(ctx context.Context, cmd cqrs.CancelMFSIPCommand) (broker.MFSIPResponse, error)

func (*CancelMFSIPUseCase) SetEventDispatcher

func (uc *CancelMFSIPUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so broker failures emit MFOrderRejectedEvent. Nil-safe.

func (*CancelMFSIPUseCase) SetEventStore

func (uc *CancelMFSIPUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type CancelOrderUseCase

type CancelOrderUseCase struct {
	// contains filtered or unexported fields
}

CancelOrderUseCase orchestrates order cancellation: broker API call -> domain event dispatch. Riskguard is not applied to cancels (cancelling reduces risk, not increases it).

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewCancelOrderUseCase

func NewCancelOrderUseCase(
	resolver BrokerResolver,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *CancelOrderUseCase

NewCancelOrderUseCase creates a CancelOrderUseCase with all dependencies injected.

func (*CancelOrderUseCase) Execute

func (uc *CancelOrderUseCase) Execute(ctx context.Context, cmd cqrs.CancelOrderCommand) (broker.OrderResponse, error)

Execute cancels the specified order and returns the broker response.

func (*CancelOrderUseCase) SetEventDispatcher

func (uc *CancelOrderUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher updates the domain event dispatcher post-construction. See PlaceOrderUseCase.SetEventDispatcher for the rationale (production wiring sets the dispatcher after the use case has already been built; without this setter the OrderCancelledEvent emission silently drops).

func (*CancelOrderUseCase) SetEventStore

func (uc *CancelOrderUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. Phase C ES.

type CancelTrailingStopUseCase

type CancelTrailingStopUseCase struct {
	// contains filtered or unexported fields
}

CancelTrailingStopUseCase deactivates a trailing stop.

func NewCancelTrailingStopUseCase

func NewCancelTrailingStopUseCase(manager TrailingStopManager, logger *slog.Logger) *CancelTrailingStopUseCase

NewCancelTrailingStopUseCase creates a CancelTrailingStopUseCase with dependencies injected.

func (*CancelTrailingStopUseCase) Execute

func (uc *CancelTrailingStopUseCase) Execute(ctx context.Context, cmd cqrs.CancelTrailingStopCommand) error

Execute cancels a trailing stop.

func (*CancelTrailingStopUseCase) SetEventDispatcher

func (uc *CancelTrailingStopUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so successful cancellation emits TrailingStopCancelledEvent. Nil-safe.

func (*CancelTrailingStopUseCase) SetEventStore

func (uc *CancelTrailingStopUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type ClearSessionDataUseCase

type ClearSessionDataUseCase struct {
	// contains filtered or unexported fields
}

ClearSessionDataUseCase clears the Kite session data attached to an MCP session without terminating the session itself. Owns the persistence step — the handler in kc/manager_commands_setup.go invokes Execute, and mcp/ tool handlers must not reach past the bus to call ClearSessionData directly (Round-5 Phase B contract for sessions).

func NewClearSessionDataUseCase

func NewClearSessionDataUseCase(sessions SessionDataClearer, logger *slog.Logger) *ClearSessionDataUseCase

NewClearSessionDataUseCase creates a ClearSessionDataUseCase with the session clearer injected via the narrow SessionDataClearer port. sessions may be nil during partial bootstrap; Execute returns an error in that case so a missing dependency surfaces rather than silently succeeding.

func (*ClearSessionDataUseCase) Execute

func (uc *ClearSessionDataUseCase) Execute(ctx context.Context, cmd cqrs.ClearSessionDataCommand) error

Execute clears the session data for the command's SessionID. Reason is logged at Info level so audit trails can correlate the clear with the lifecycle narrative (post-credential-register vs profile-check-failed).

On successful SQL write the use case appends a session.cleared event to the domain audit log (Phase C event sourcing). The append is best-effort — the SQL write is the source of truth, and an audit-log failure must not break the login flow that drove the clear.

func (*ClearSessionDataUseCase) SetEventStore

func (uc *ClearSessionDataUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. Optional — a nil appender disables the append-after-clear side effect (existing behavior). Called from app/wire.go once the eventsourcing store is constructed.

type CloseAllPositionsUseCase

type CloseAllPositionsUseCase struct {
	// contains filtered or unexported fields
}

CloseAllPositionsUseCase exits all open positions by placing opposite MARKET orders. Pipeline: fetch positions -> filter -> riskguard per-order -> place orders -> events.

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewCloseAllPositionsUseCase

func NewCloseAllPositionsUseCase(
	resolver BrokerResolver,
	guard *riskguard.Guard,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *CloseAllPositionsUseCase

NewCloseAllPositionsUseCase creates a CloseAllPositionsUseCase with all dependencies injected.

func (*CloseAllPositionsUseCase) Execute

func (uc *CloseAllPositionsUseCase) Execute(ctx context.Context, email, productFilter string) (*CloseAllResult, error)

Execute closes all matching positions and returns the aggregate result.

func (*CloseAllPositionsUseCase) ExecuteCommand

func (uc *CloseAllPositionsUseCase) ExecuteCommand(ctx context.Context, cmd cqrs.CloseAllPositionsCommand) (*CloseAllResult, error)

ExecuteCommand is the CQRS-bus adapter: unpacks a CloseAllPositionsCommand and delegates to Execute. Preserves Execute's raw-arg signature for the existing test corpus while giving the CommandBus a typed entry point.

func (*CloseAllPositionsUseCase) SetEventDispatcher

func (uc *CloseAllPositionsUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher updates the domain event dispatcher post-construction. See PlaceOrderUseCase.SetEventDispatcher for the rationale.

type CloseAllResult

type CloseAllResult struct {
	SuccessCount  int                `json:"success_count"`
	ErrorCount    int                `json:"error_count"`
	Total         int                `json:"total"`
	ProductFilter string             `json:"product_filter"`
	Results       []CloseEntryResult `json:"results"`
}

CloseAllResult contains the outcome of closing all positions.

type CloseEntryResult

type CloseEntryResult struct {
	Tradingsymbol string `json:"tradingsymbol"`
	Exchange      string `json:"exchange"`
	Quantity      int    `json:"quantity"`
	Direction     string `json:"direction"`
	OrderID       string `json:"order_id,omitempty"`
	Error         string `json:"error,omitempty"`
}

CloseEntryResult holds the outcome for a single position close attempt.

type ClosePositionResult

type ClosePositionResult struct {
	OrderID     string  `json:"order_id"`
	Instrument  string  `json:"instrument"`
	Quantity    int     `json:"quantity"`
	Direction   string  `json:"direction"`
	Product     string  `json:"product"`
	PositionPnL float64 `json:"position_pnl"`
}

ClosePositionResult contains the outcome of closing a position.

type ClosePositionUseCase

type ClosePositionUseCase struct {
	// contains filtered or unexported fields
}

ClosePositionUseCase closes a single position by placing an opposite MARKET order. Pipeline: find position -> riskguard check -> place opposite order -> domain event.

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewClosePositionUseCase

func NewClosePositionUseCase(
	resolver BrokerResolver,
	guard *riskguard.Guard,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *ClosePositionUseCase

NewClosePositionUseCase creates a ClosePositionUseCase with all dependencies injected.

func (*ClosePositionUseCase) Execute

func (uc *ClosePositionUseCase) Execute(ctx context.Context, email, exchange, symbol, productFilter string) (*ClosePositionResult, error)

Execute finds the matching position and places an opposite MARKET order to close it.

func (*ClosePositionUseCase) ExecuteCommand

func (uc *ClosePositionUseCase) ExecuteCommand(ctx context.Context, cmd cqrs.ClosePositionCommand) (*ClosePositionResult, error)

ExecuteCommand is the CQRS-bus adapter: unpacks a ClosePositionCommand and delegates to Execute. Preserves Execute's raw-arg signature for the existing test corpus while giving the CommandBus a typed entry point.

func (*ClosePositionUseCase) SetEventDispatcher

func (uc *ClosePositionUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher updates the domain event dispatcher post-construction. See PlaceOrderUseCase.SetEventDispatcher for the rationale (production wiring sets the dispatcher after the use case has already been built; without this setter the PositionClosedEvent emission silently drops).

type CompositeAlertStore

type CompositeAlertStore interface {
	AddComposite(email, name string, logic domain.CompositeLogic, conds []domain.CompositeCondition) (string, error)
}

CompositeAlertStore is the subset of kc.AlertStoreInterface needed to create composite alerts. Scoped narrowly per Interface Segregation.

type ConsentExporter

type ConsentExporter interface {
	ExportConsentLog(emailHash string) ([]any, error)
}

ConsentExporter retrieves the full consent_log history.

type ConsentWithdrawer

type ConsentWithdrawer interface {
	MarkWithdrawnByEmailHash(emailHash string, withdrawnAt time.Time,
		noticeVersion, reason, ipAddress, userAgent string) (int64, error)
}

ConsentWithdrawer is the narrow port the use case needs from the audit consent store. The store hashes nothing — the use case passes the already-hashed email + the operational fields.

type ConvertPositionUseCase

type ConvertPositionUseCase struct {
	// contains filtered or unexported fields
}

ConvertPositionUseCase converts a position from one product type to another.

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewConvertPositionUseCase

func NewConvertPositionUseCase(resolver BrokerResolver, logger *slog.Logger) *ConvertPositionUseCase

NewConvertPositionUseCase creates a ConvertPositionUseCase with all dependencies injected.

func (*ConvertPositionUseCase) Execute

func (uc *ConvertPositionUseCase) Execute(ctx context.Context, cmd cqrs.ConvertPositionCommand) (bool, error)

Execute converts a position from one product type to another.

func (*ConvertPositionUseCase) SetEventDispatcher

func (uc *ConvertPositionUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so the use case emits a domain.PositionConvertedEvent on success — replacing the prior untyped appendAuxEvent payload with a stable typed schema for projector consumers. Nil-safe: when unset, only the legacy aux-event path runs (preserves backward compatibility for tests / bootstrap configurations that don't wire the dispatcher). Both paths fire on success during the migration window so audit consumers depending on the historical untyped row aren't broken.

func (*ConvertPositionUseCase) SetEventStore

func (uc *ConvertPositionUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type CreateAlertUseCase

type CreateAlertUseCase struct {
	// contains filtered or unexported fields
}

CreateAlertUseCase creates a new price alert for a user.

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewCreateAlertUseCase

func NewCreateAlertUseCase(
	store AlertStore,
	instruments InstrumentResolver,
	logger *slog.Logger,
) *CreateAlertUseCase

NewCreateAlertUseCase creates a CreateAlertUseCase with all dependencies injected.

func (*CreateAlertUseCase) Execute

func (uc *CreateAlertUseCase) Execute(ctx context.Context, cmd cqrs.CreateAlertCommand) (string, error)

Execute creates an alert and returns the alert ID.

func (*CreateAlertUseCase) SetEventDispatcher

func (uc *CreateAlertUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires an event dispatcher so AlertCreatedEvent is emitted on successful creation. Dispatcher feeds the Projector (read model) and runtime subscribers. Audit-log persistence is handled separately by SetEventStore — the dispatcher path for alert.created is no longer subscribed to the persister in wire.go (Phase C: use case owns the audit write to avoid double-emit). Optional — callers without a dispatcher skip the dispatch step.

func (*CreateAlertUseCase) SetEventStore

func (uc *CreateAlertUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. When set, Execute appends an alert.created StoredEvent directly after a successful insert. Phase C event sourcing. Nil-safe — unset event stores skip the append.

type CreateCompositeAlertUseCase

type CreateCompositeAlertUseCase struct {
	// contains filtered or unexported fields
}

CreateCompositeAlertUseCase creates a composite alert for a user.

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewCreateCompositeAlertUseCase

func NewCreateCompositeAlertUseCase(
	store CompositeAlertStore,
	instruments InstrumentResolver,
	logger *slog.Logger,
) *CreateCompositeAlertUseCase

NewCreateCompositeAlertUseCase wires the use case with its dependencies.

func (*CreateCompositeAlertUseCase) Execute

func (uc *CreateCompositeAlertUseCase) Execute(ctx context.Context, cmd cqrs.CreateCompositeAlertCommand) (string, error)

Execute validates the command, resolves instrument tokens for every leg, and dispatches the composite write to the store. Returns the alert ID.

func (*CreateCompositeAlertUseCase) SetEventStore

func (uc *CreateCompositeAlertUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. When set, Execute appends an alert.created StoredEvent after successful persistence. Phase C ES.

type CreateWatchlistResult

type CreateWatchlistResult struct {
	ID   string `json:"id"`
	Name string `json:"name"`
}

CreateWatchlistResult holds the result of creating a watchlist.

type CreateWatchlistUseCase

type CreateWatchlistUseCase struct {
	// contains filtered or unexported fields
}

CreateWatchlistUseCase creates a new named watchlist.

func NewCreateWatchlistUseCase

func NewCreateWatchlistUseCase(store WatchlistStore, logger *slog.Logger) *CreateWatchlistUseCase

NewCreateWatchlistUseCase creates a CreateWatchlistUseCase with dependencies injected.

func (*CreateWatchlistUseCase) Execute

func (uc *CreateWatchlistUseCase) Execute(ctx context.Context, cmd cqrs.CreateWatchlistCommand) (*CreateWatchlistResult, error)

Execute creates a new watchlist, checking for duplicates.

func (*CreateWatchlistUseCase) SetEventDispatcher

func (uc *CreateWatchlistUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the domain event dispatcher so a typed domain.WatchlistCreatedEvent is dispatched on every successful create. The dispatcher path is for runtime subscribers (read-side projector, future consumers); audit persistence is owned by SetEventStore via the appendWatchlistEvent direct path to avoid double-write — wire.go does NOT subscribe makeEventPersister for watchlist.* event types. Pattern mirrors CreateAlertUseCase. Nil-safe.

func (*CreateWatchlistUseCase) SetEventStore

func (uc *CreateWatchlistUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. Phase C ES.

type CredentialSetter

type CredentialSetter interface {
	Set(email string, entry any)
}

CredentialSetter abstracts credential persistence for updating credentials.

type CredentialUpdater

type CredentialUpdater interface {
	Delete(email string)
	Set(email, apiKey, apiSecret string)
	Has(email string) bool
}

CredentialUpdater abstracts credential persistence for account use cases. Delete removes a user's credentials (used by DeleteMyAccount). Set installs/updates a user's credentials (used by UpdateMyCredentials). The apiKey/apiSecret pair is passed as primitive strings — the use case should not import kc internal types (circular dependency risk with kc → usecases). Has reports whether an entry already exists for the email — needed by UpdateMyCredentials to tell first-time registration (CredentialRegistered event) from replacement (CredentialRotated event). Implementations wrap the kc.KiteCredentialStore.Set call behind this port.

type DataExport

type DataExport struct {
	GeneratedAtUTC time.Time `json:"generated_at_utc"`
	Email          string    `json:"email"`
	EmailHash      string    `json:"email_hash"`
	RetentionFrom  time.Time `json:"retention_from_utc"`

	ToolCalls    DataExportSection `json:"tool_calls"`
	Alerts       DataExportSection `json:"alerts"`
	Watchlists   DataExportSection `json:"watchlists"`
	PaperTrades  DataExportSection `json:"paper_trades"`
	Sessions     DataExportSection `json:"sessions"`
	Credentials  DataExportSection `json:"credentials"`
	Consent      DataExportSection `json:"consent_log"`
	DomainEvents DataExportSection `json:"domain_events"`
}

DataExport is the canonical export shape returned to the user. JSON keys are stable and lower_snake_case so external automation can rely on them across versions.

type DataExportPorts

type DataExportPorts struct {
	ToolCalls    ToolCallExporter
	Alerts       AlertExporter
	Watchlists   WatchlistExporter
	PaperTrades  PaperTradeExporter
	Sessions     SessionExporter
	Consent      ConsentExporter
	DomainEvents DomainEventExporter
	Hasher       EmailHasher // reused from consent_usecases.go
}

DataExportPorts groups all eight port types in one struct so the use-case constructor signature stays manageable. Any field may be nil — the corresponding section will be reported as unavailable.

type DataExportSection

type DataExportSection struct {
	Rows  []any  `json:"rows,omitempty"`
	Count int    `json:"count"`
	Note  string `json:"note,omitempty"`
}

DataExportSection wraps a section's rows + an optional unavailability note. Unavailable sections retain their key in the output JSON so downstream automated tooling sees a stable schema regardless of which stores are wired.

type DeleteAlertUseCase

type DeleteAlertUseCase struct {
	// contains filtered or unexported fields
}

DeleteAlertUseCase deletes a specific alert.

func NewDeleteAlertUseCase

func NewDeleteAlertUseCase(store AlertReader, logger *slog.Logger) *DeleteAlertUseCase

NewDeleteAlertUseCase creates a DeleteAlertUseCase with dependencies injected.

func (*DeleteAlertUseCase) Execute

func (uc *DeleteAlertUseCase) Execute(ctx context.Context, cmd cqrs.DeleteAlertCommand) error

Execute deletes an alert by ID.

func (*DeleteAlertUseCase) SetEventDispatcher

func (uc *DeleteAlertUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires an event dispatcher so AlertDeletedEvent is emitted on successful deletion. Dispatcher drives the Projector (read model). Audit-log persistence is handled separately by SetEventStore — the dispatcher→persister path for alert.deleted was dropped in Phase C to prevent double-emit. Optional — unset dispatcher skips the dispatch.

func (*DeleteAlertUseCase) SetEventStore

func (uc *DeleteAlertUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. When set, Execute appends an alert.deleted StoredEvent directly after successful deletion. Phase C event sourcing. Nil-safe.

type DeleteGTTUseCase

type DeleteGTTUseCase struct {
	// contains filtered or unexported fields
}

DeleteGTTUseCase orchestrates GTT order deletion.

func NewDeleteGTTUseCase

func NewDeleteGTTUseCase(resolver BrokerResolver, logger *slog.Logger) *DeleteGTTUseCase

NewDeleteGTTUseCase creates a DeleteGTTUseCase with all dependencies injected.

func (*DeleteGTTUseCase) Execute

func (uc *DeleteGTTUseCase) Execute(ctx context.Context, cmd cqrs.DeleteGTTCommand) (broker.GTTResponse, error)

Execute deletes a GTT order.

func (*DeleteGTTUseCase) SetEventDispatcher

func (uc *DeleteGTTUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so broker failures emit GTTRejectedEvent. Nil-safe.

func (*DeleteGTTUseCase) SetEventStore

func (uc *DeleteGTTUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type DeleteMyAccountUseCase

type DeleteMyAccountUseCase struct {
	// contains filtered or unexported fields
}

DeleteMyAccountUseCase permanently deletes a user's account and all data.

func NewDeleteMyAccountUseCase

func NewDeleteMyAccountUseCase(deps AccountDependencies, logger *slog.Logger) *DeleteMyAccountUseCase

NewDeleteMyAccountUseCase creates a DeleteMyAccountUseCase with dependencies injected.

func (*DeleteMyAccountUseCase) Execute

func (uc *DeleteMyAccountUseCase) Execute(ctx context.Context, cmd cqrs.DeleteMyAccountCommand) error

Execute deletes the user's account and all associated data.

func (*DeleteMyAccountUseCase) SetEventStore

func (uc *DeleteMyAccountUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. When set, Execute appends a credential.revoked StoredEvent (Reason="account_deletion") after the credential Delete so the account-deletion path shares the same credential-lifecycle stream as RevokeCredentialsCommand. Phase C-Credentials (#33). Nil-safe.

type DeleteNativeAlertUseCase

type DeleteNativeAlertUseCase struct {
	// contains filtered or unexported fields
}

DeleteNativeAlertUseCase deletes one or more native alerts.

func NewDeleteNativeAlertUseCase

func NewDeleteNativeAlertUseCase(logger *slog.Logger) *DeleteNativeAlertUseCase

NewDeleteNativeAlertUseCase creates a DeleteNativeAlertUseCase with dependencies injected.

func (*DeleteNativeAlertUseCase) Execute

func (uc *DeleteNativeAlertUseCase) Execute(ctx context.Context, client NativeAlertClient, cmd cqrs.DeleteNativeAlertCommand) error

Execute deletes native alert(s).

func (*DeleteNativeAlertUseCase) SetEventDispatcher

func (uc *DeleteNativeAlertUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so successful deletion emits NativeAlertDeletedEvent (one per UUID). Nil-safe.

func (*DeleteNativeAlertUseCase) SetEventStore

func (uc *DeleteNativeAlertUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type DeleteOAuthClientUseCase

type DeleteOAuthClientUseCase struct {
	// contains filtered or unexported fields
}

DeleteOAuthClientUseCase deletes an OAuth dynamic-client registration.

func NewDeleteOAuthClientUseCase

func NewDeleteOAuthClientUseCase(s OAuthClientStore, logger *slog.Logger) *DeleteOAuthClientUseCase

NewDeleteOAuthClientUseCase builds the use case.

func (*DeleteOAuthClientUseCase) Execute

func (uc *DeleteOAuthClientUseCase) Execute(_ context.Context, cmd cqrs.DeleteOAuthClientCommand) error

Execute runs the use case.

type DeleteWatchlistResult

type DeleteWatchlistResult struct {
	Name      string `json:"name"`
	ItemCount int    `json:"item_count"`
}

DeleteWatchlistResult holds the result of deleting a watchlist.

type DeleteWatchlistUseCase

type DeleteWatchlistUseCase struct {
	// contains filtered or unexported fields
}

DeleteWatchlistUseCase deletes a watchlist and all its items.

func NewDeleteWatchlistUseCase

func NewDeleteWatchlistUseCase(store WatchlistStore, logger *slog.Logger) *DeleteWatchlistUseCase

NewDeleteWatchlistUseCase creates a DeleteWatchlistUseCase with dependencies injected.

func (*DeleteWatchlistUseCase) Execute

func (uc *DeleteWatchlistUseCase) Execute(ctx context.Context, cmd cqrs.DeleteWatchlistCommand) (*DeleteWatchlistResult, error)

Execute deletes a watchlist by ID.

func (*DeleteWatchlistUseCase) SetEventDispatcher

func (uc *DeleteWatchlistUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the domain event dispatcher for typed WatchlistDeletedEvent emission. See CreateWatchlistUseCase SetEventDispatcher for the dispatch-vs-audit rationale. Nil-safe.

func (*DeleteWatchlistUseCase) SetEventStore

func (uc *DeleteWatchlistUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. Phase C ES.

type DomainEventExporter

type DomainEventExporter interface {
	ExportDomainEvents(emailHash string, since time.Time) ([]any, error)
}

DomainEventExporter retrieves domain events keyed by email_hash.

type EmailHasher

type EmailHasher interface {
	HashEmail(email string) string
}

EmailHasher abstracts the SHA-256 hashing helper. Defined as a port so the use case stays free of an audit-package import (audit imports ports → cycle); the manager wires this to audit.HashEmail.

type EventAppender

type EventAppender interface {
	Append(events ...eventsourcing.StoredEvent) error
	AppendToOutbox(evt eventsourcing.StoredEvent) error
	NextSequence(aggregateID string) (int64, error)
}

EventAppender is a narrow port over eventsourcing.EventStore that the use cases use to write domain events to the audit log. The full store exposes LoadEvents / LoadEventsSince which are read-model concerns; the use case only needs to append and ask for the next sequence number. kc/eventsourcing.EventStore satisfies this natively.

AppendToOutbox is the durability-first variant for hot mutation paths (place_order, modify_order, cancel_order, create_alert) where audit loss after the broker side-effect is unacceptable. The implementation writes to a small staging table; an async pump drains it into the canonical domain_events table. Crash recovery is automatic on the next process restart. Use cases that don't need this guarantee call Append directly. See kc/eventsourcing/outbox.go for full design.

type EventDispatcherPort

type EventDispatcherPort interface {
	Dispatch(event domain.Event)
}

EventDispatcherPort is the narrow dispatcher port for emitting ConsentWithdrawnEvent. nil-safe — the use case skips dispatch when no dispatcher is wired (DevMode, tests).

type ExportMyDataUseCase

type ExportMyDataUseCase struct {
	// contains filtered or unexported fields
}

ExportMyDataUseCase orchestrates the §11 portability dump. Any per-section error is captured into that section's Note so a partial-data store doesn't fail the whole export. Hard errors (validation, missing hasher) return up the stack.

func NewExportMyDataUseCase

func NewExportMyDataUseCase(ports DataExportPorts, logger *slog.Logger) *ExportMyDataUseCase

NewExportMyDataUseCase builds the use case.

func (*ExportMyDataUseCase) Execute

func (uc *ExportMyDataUseCase) Execute(ctx context.Context, cmd cqrs.ExportMyDataCommand) (*DataExport, error)

Execute runs the export. Validates inputs, then queries every port in turn. A single nil port produces a section with Note="not wired" and proceeds. A port that errors produces a section with the error recorded in Note (keeping the schema stable for downstream tooling).

func (*ExportMyDataUseCase) SetClock

func (uc *ExportMyDataUseCase) SetClock(now func() time.Time)

SetClock overrides the time source. Tests use this to assert deterministic generated_at_utc.

type FamilyInvitationEntry

type FamilyInvitationEntry struct {
	ID           string    `json:"id"`
	InvitedEmail string    `json:"invited_email"`
	Status       string    `json:"status"`
	ExpiresAt    time.Time `json:"expires_at"`
}

FamilyInvitationEntry is one pending invitation row in the listing.

type FamilyInvitationReader

type FamilyInvitationReader interface {
	ListByAdmin(adminEmail string) []*users.FamilyInvitation
}

FamilyInvitationReader reads pending invitations for an admin.

type FamilyInvitationWriter

type FamilyInvitationWriter interface {
	Create(inv *users.FamilyInvitation) error
}

FamilyInvitationWriter persists newly created family invitations.

type FamilyMemberEntry

type FamilyMemberEntry struct {
	Email     string    `json:"email"`
	Role      string    `json:"role"`
	Status    string    `json:"status"`
	LastLogin time.Time `json:"last_login,omitempty"`
}

FamilyMemberEntry is one member row in the listing.

type FamilyProvider

type FamilyProvider interface {
	ListMembers(adminEmail string) []*users.User
	CanInvite(adminEmail string) (ok bool, current int, max int)
	MaxUsers(adminEmail string) int
	RemoveMember(adminEmail, memberEmail string) error
}

FamilyProvider is the narrow interface the family use cases need from the kc.FamilyService. Defined here so usecases remain decoupled from the kc package (no import cycle).

type GetActivityForWidgetUseCase

type GetActivityForWidgetUseCase struct {
	// contains filtered or unexported fields
}

GetActivityForWidgetUseCase fetches recent audit entries with stats for the activity widget.

func NewGetActivityForWidgetUseCase

func NewGetActivityForWidgetUseCase(store WidgetAuditStore, logger *slog.Logger) *GetActivityForWidgetUseCase

NewGetActivityForWidgetUseCase creates a GetActivityForWidgetUseCase.

func (*GetActivityForWidgetUseCase) Execute

func (uc *GetActivityForWidgetUseCase) Execute(ctx context.Context, query cqrs.GetWidgetActivityQuery) (*WidgetActivityResult, error)

Execute fetches and formats activity data for the widget.

type GetAlertsForWidgetUseCase

type GetAlertsForWidgetUseCase struct {
	// contains filtered or unexported fields
}

GetAlertsForWidgetUseCase fetches alerts enriched with current LTP for the alerts widget.

func NewGetAlertsForWidgetUseCase

func NewGetAlertsForWidgetUseCase(resolver BrokerResolver, store WidgetAlertStore, logger *slog.Logger) *GetAlertsForWidgetUseCase

NewGetAlertsForWidgetUseCase creates a GetAlertsForWidgetUseCase.

func (*GetAlertsForWidgetUseCase) Execute

func (uc *GetAlertsForWidgetUseCase) Execute(ctx context.Context, query cqrs.GetWidgetAlertsQuery) (*WidgetAlertsResult, error)

Execute fetches and formats alert data for the widget.

type GetBasketMarginsUseCase

type GetBasketMarginsUseCase struct {
	// contains filtered or unexported fields
}

GetBasketMarginsUseCase calculates combined margin for a basket of orders.

func NewGetBasketMarginsUseCase

func NewGetBasketMarginsUseCase(resolver BrokerResolver, logger *slog.Logger) *GetBasketMarginsUseCase

func (*GetBasketMarginsUseCase) Execute

func (uc *GetBasketMarginsUseCase) Execute(ctx context.Context, query cqrs.GetBasketMarginsQuery) (any, error)

type GetGTTsUseCase

type GetGTTsUseCase struct {
	// contains filtered or unexported fields
}

GetGTTsUseCase retrieves all GTT orders for a user.

func NewGetGTTsUseCase

func NewGetGTTsUseCase(resolver BrokerResolver, logger *slog.Logger) *GetGTTsUseCase

NewGetGTTsUseCase creates a GetGTTsUseCase with all dependencies injected.

func (*GetGTTsUseCase) Execute

func (uc *GetGTTsUseCase) Execute(ctx context.Context, query cqrs.GetGTTsQuery) ([]broker.GTTOrder, error)

Execute retrieves all GTT orders for the user.

type GetHistoricalDataUseCase

type GetHistoricalDataUseCase struct {
	// contains filtered or unexported fields
}

GetHistoricalDataUseCase retrieves historical candle data for an instrument.

func NewGetHistoricalDataUseCase

func NewGetHistoricalDataUseCase(resolver BrokerResolver, logger *slog.Logger) *GetHistoricalDataUseCase

NewGetHistoricalDataUseCase creates a GetHistoricalDataUseCase with all dependencies injected.

func (*GetHistoricalDataUseCase) Execute

func (uc *GetHistoricalDataUseCase) Execute(ctx context.Context, email string, query cqrs.GetHistoricalDataQuery) ([]broker.HistoricalCandle, error)

Execute retrieves historical candle data for the given instrument.

type GetLTPUseCase

type GetLTPUseCase struct {
	// contains filtered or unexported fields
}

GetLTPUseCase retrieves the last traded price for instruments.

func NewGetLTPUseCase

func NewGetLTPUseCase(resolver BrokerResolver, logger *slog.Logger) *GetLTPUseCase

NewGetLTPUseCase creates a GetLTPUseCase with all dependencies injected.

func (*GetLTPUseCase) Execute

func (uc *GetLTPUseCase) Execute(ctx context.Context, email string, query cqrs.GetLTPQuery) (map[string]broker.LTP, error)

Execute retrieves the last traded price for the given instruments.

type GetMFHoldingsUseCase

type GetMFHoldingsUseCase struct {
	// contains filtered or unexported fields
}

GetMFHoldingsUseCase retrieves all mutual fund holdings.

func NewGetMFHoldingsUseCase

func NewGetMFHoldingsUseCase(resolver BrokerResolver, logger *slog.Logger) *GetMFHoldingsUseCase

func (*GetMFHoldingsUseCase) Execute

func (uc *GetMFHoldingsUseCase) Execute(ctx context.Context, query cqrs.GetMFHoldingsQuery) ([]broker.MFHolding, error)

type GetMFOrdersUseCase

type GetMFOrdersUseCase struct {
	// contains filtered or unexported fields
}

GetMFOrdersUseCase retrieves all mutual fund orders.

func NewGetMFOrdersUseCase

func NewGetMFOrdersUseCase(resolver BrokerResolver, logger *slog.Logger) *GetMFOrdersUseCase

func (*GetMFOrdersUseCase) Execute

func (uc *GetMFOrdersUseCase) Execute(ctx context.Context, query cqrs.GetMFOrdersQuery) ([]broker.MFOrder, error)

type GetMFSIPsUseCase

type GetMFSIPsUseCase struct {
	// contains filtered or unexported fields
}

GetMFSIPsUseCase retrieves all mutual fund SIPs.

func NewGetMFSIPsUseCase

func NewGetMFSIPsUseCase(resolver BrokerResolver, logger *slog.Logger) *GetMFSIPsUseCase

func (*GetMFSIPsUseCase) Execute

func (uc *GetMFSIPsUseCase) Execute(ctx context.Context, query cqrs.GetMFSIPsQuery) ([]broker.MFSIP, error)

type GetMarginsUseCase

type GetMarginsUseCase struct {
	// contains filtered or unexported fields
}

GetMarginsUseCase retrieves the user's account margins.

func NewGetMarginsUseCase

func NewGetMarginsUseCase(resolver BrokerResolver, logger *slog.Logger) *GetMarginsUseCase

NewGetMarginsUseCase creates a GetMarginsUseCase with all dependencies injected.

func (*GetMarginsUseCase) Execute

func (uc *GetMarginsUseCase) Execute(ctx context.Context, query cqrs.GetMarginsQuery) (broker.Margins, error)

Execute retrieves the user's margins.

type GetNativeAlertHistoryUseCase

type GetNativeAlertHistoryUseCase struct {
	// contains filtered or unexported fields
}

GetNativeAlertHistoryUseCase retrieves trigger history for a native alert.

func NewGetNativeAlertHistoryUseCase

func NewGetNativeAlertHistoryUseCase(logger *slog.Logger) *GetNativeAlertHistoryUseCase

NewGetNativeAlertHistoryUseCase creates a GetNativeAlertHistoryUseCase with dependencies injected.

func (*GetNativeAlertHistoryUseCase) Execute

func (uc *GetNativeAlertHistoryUseCase) Execute(ctx context.Context, client NativeAlertClient, query cqrs.GetNativeAlertHistoryQuery) (any, error)

Execute retrieves alert history.

type GetOHLCUseCase

type GetOHLCUseCase struct {
	// contains filtered or unexported fields
}

GetOHLCUseCase retrieves OHLC data for instruments.

func NewGetOHLCUseCase

func NewGetOHLCUseCase(resolver BrokerResolver, logger *slog.Logger) *GetOHLCUseCase

NewGetOHLCUseCase creates a GetOHLCUseCase with all dependencies injected.

func (*GetOHLCUseCase) Execute

func (uc *GetOHLCUseCase) Execute(ctx context.Context, email string, query cqrs.GetOHLCQuery) (map[string]broker.OHLC, error)

Execute retrieves OHLC data for the given instruments.

type GetOrderChargesUseCase

type GetOrderChargesUseCase struct {
	// contains filtered or unexported fields
}

GetOrderChargesUseCase calculates brokerage, taxes, and charges for orders.

func NewGetOrderChargesUseCase

func NewGetOrderChargesUseCase(resolver BrokerResolver, logger *slog.Logger) *GetOrderChargesUseCase

func (*GetOrderChargesUseCase) Execute

func (uc *GetOrderChargesUseCase) Execute(ctx context.Context, query cqrs.GetOrderChargesQuery) (any, error)

type GetOrderHistoryUseCase

type GetOrderHistoryUseCase struct {
	// contains filtered or unexported fields
}

GetOrderHistoryUseCase retrieves the state history of a specific order.

func NewGetOrderHistoryUseCase

func NewGetOrderHistoryUseCase(resolver BrokerResolver, logger *slog.Logger) *GetOrderHistoryUseCase

NewGetOrderHistoryUseCase creates a GetOrderHistoryUseCase with all dependencies injected.

func (*GetOrderHistoryUseCase) Execute

func (uc *GetOrderHistoryUseCase) Execute(ctx context.Context, query cqrs.GetOrderHistoryQuery) ([]broker.Order, error)

Execute retrieves the state history for a specific order.

type GetOrderMarginsUseCase

type GetOrderMarginsUseCase struct {
	// contains filtered or unexported fields
}

GetOrderMarginsUseCase calculates margin required for orders.

func NewGetOrderMarginsUseCase

func NewGetOrderMarginsUseCase(resolver BrokerResolver, logger *slog.Logger) *GetOrderMarginsUseCase

func (*GetOrderMarginsUseCase) Execute

func (uc *GetOrderMarginsUseCase) Execute(ctx context.Context, query cqrs.GetOrderMarginsQuery) (any, error)

type GetOrderTradesUseCase

type GetOrderTradesUseCase struct {
	// contains filtered or unexported fields
}

GetOrderTradesUseCase retrieves executed trades for a specific order.

func NewGetOrderTradesUseCase

func NewGetOrderTradesUseCase(resolver BrokerResolver, logger *slog.Logger) *GetOrderTradesUseCase

NewGetOrderTradesUseCase creates a GetOrderTradesUseCase with all dependencies injected.

func (*GetOrderTradesUseCase) Execute

func (uc *GetOrderTradesUseCase) Execute(ctx context.Context, query cqrs.GetOrderTradesQuery) ([]broker.Trade, error)

Execute retrieves executed trades for a specific order.

type GetOrdersForWidgetUseCase

type GetOrdersForWidgetUseCase struct {
	// contains filtered or unexported fields
}

GetOrdersForWidgetUseCase fetches audit-tracked orders enriched with broker status for the orders widget.

func NewGetOrdersForWidgetUseCase

func NewGetOrdersForWidgetUseCase(resolver BrokerResolver, store WidgetAuditStore, logger *slog.Logger) *GetOrdersForWidgetUseCase

NewGetOrdersForWidgetUseCase creates a GetOrdersForWidgetUseCase.

func (*GetOrdersForWidgetUseCase) Execute

func (uc *GetOrdersForWidgetUseCase) Execute(ctx context.Context, query cqrs.GetWidgetOrdersQuery) (*WidgetOrdersResult, error)

Execute fetches and formats order data for the widget.

type GetOrdersUseCase

type GetOrdersUseCase struct {
	// contains filtered or unexported fields
}

GetOrdersUseCase retrieves all orders for the current trading day.

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewGetOrdersUseCase

func NewGetOrdersUseCase(resolver BrokerResolver, logger *slog.Logger) *GetOrdersUseCase

NewGetOrdersUseCase creates a GetOrdersUseCase with all dependencies injected.

func (*GetOrdersUseCase) Execute

func (uc *GetOrdersUseCase) Execute(ctx context.Context, query cqrs.GetOrdersQuery) ([]broker.Order, error)

Execute retrieves the user's orders for the current trading day.

type GetPnLJournalUseCase

type GetPnLJournalUseCase struct {
	// contains filtered or unexported fields
}

GetPnLJournalUseCase retrieves P&L journal data.

func NewGetPnLJournalUseCase

func NewGetPnLJournalUseCase(service PnLService, logger *slog.Logger) *GetPnLJournalUseCase

NewGetPnLJournalUseCase creates a GetPnLJournalUseCase with dependencies injected.

func (*GetPnLJournalUseCase) Execute

func (uc *GetPnLJournalUseCase) Execute(ctx context.Context, query cqrs.GetPnLJournalQuery) (*alerts.PnLJournalResult, error)

Execute retrieves the P&L journal.

type GetPortfolioForWidgetUseCase

type GetPortfolioForWidgetUseCase struct {
	// contains filtered or unexported fields
}

GetPortfolioForWidgetUseCase fetches holdings + positions in parallel and formats them for the portfolio widget.

func NewGetPortfolioForWidgetUseCase

func NewGetPortfolioForWidgetUseCase(resolver BrokerResolver, logger *slog.Logger) *GetPortfolioForWidgetUseCase

NewGetPortfolioForWidgetUseCase creates a GetPortfolioForWidgetUseCase.

func (*GetPortfolioForWidgetUseCase) Execute

func (uc *GetPortfolioForWidgetUseCase) Execute(ctx context.Context, query cqrs.GetWidgetPortfolioQuery) (*WidgetPortfolioResult, error)

Execute fetches and formats portfolio data for the widget.

type GetPortfolioUseCase

type GetPortfolioUseCase struct {
	// contains filtered or unexported fields
}

GetPortfolioUseCase retrieves a user's full portfolio (holdings + positions).

Wave D Phase 3 Package 5 (Logger sweep): logger is the kc/logger.Logger port; constructor takes *slog.Logger and converts via logport.NewSlog.

func NewGetPortfolioUseCase

func NewGetPortfolioUseCase(resolver BrokerResolver, logger *slog.Logger) *GetPortfolioUseCase

NewGetPortfolioUseCase creates a GetPortfolioUseCase with all dependencies injected.

func (*GetPortfolioUseCase) Execute

func (uc *GetPortfolioUseCase) Execute(ctx context.Context, query cqrs.GetPortfolioQuery) (*PortfolioResult, error)

Execute retrieves holdings and positions for the user.

type GetProfileUseCase

type GetProfileUseCase struct {
	// contains filtered or unexported fields
}

GetProfileUseCase retrieves the user's broker profile.

func NewGetProfileUseCase

func NewGetProfileUseCase(resolver BrokerResolver, logger *slog.Logger) *GetProfileUseCase

NewGetProfileUseCase creates a GetProfileUseCase with all dependencies injected.

func (*GetProfileUseCase) Execute

func (uc *GetProfileUseCase) Execute(ctx context.Context, query cqrs.GetProfileQuery) (broker.Profile, error)

Execute retrieves the user's broker profile.

type GetQuotesUseCase

type GetQuotesUseCase struct {
	// contains filtered or unexported fields
}

GetQuotesUseCase retrieves full market quotes for instruments.

func NewGetQuotesUseCase

func NewGetQuotesUseCase(resolver BrokerResolver, logger *slog.Logger) *GetQuotesUseCase

NewGetQuotesUseCase creates a GetQuotesUseCase with all dependencies injected.

func (*GetQuotesUseCase) Execute

func (uc *GetQuotesUseCase) Execute(ctx context.Context, email string, query cqrs.GetQuotesQuery) (map[string]broker.Quote, error)

Execute retrieves full market quotes for the given instruments.

type GetTradesUseCase

type GetTradesUseCase struct {
	// contains filtered or unexported fields
}

GetTradesUseCase retrieves all executed trades for the current trading day.

func NewGetTradesUseCase

func NewGetTradesUseCase(resolver BrokerResolver, logger *slog.Logger) *GetTradesUseCase

NewGetTradesUseCase creates a GetTradesUseCase with all dependencies injected.

func (*GetTradesUseCase) Execute

func (uc *GetTradesUseCase) Execute(ctx context.Context, query cqrs.GetTradesQuery) ([]broker.Trade, error)

Execute retrieves the user's trades for the current trading day.

type GetWatchlistUseCase

type GetWatchlistUseCase struct {
	// contains filtered or unexported fields
}

GetWatchlistUseCase retrieves items in a watchlist.

func NewGetWatchlistUseCase

func NewGetWatchlistUseCase(store WatchlistStore, logger *slog.Logger) *GetWatchlistUseCase

NewGetWatchlistUseCase creates a GetWatchlistUseCase with dependencies injected.

func (*GetWatchlistUseCase) Execute

func (uc *GetWatchlistUseCase) Execute(ctx context.Context, query cqrs.GetWatchlistQuery) ([]*watchlist.WatchlistItem, error)

Execute retrieves all items in a watchlist.

type InstrumentResolver

type InstrumentResolver interface {
	GetInstrumentToken(exchange, tradingsymbol string) (uint32, error)
}

InstrumentResolver looks up instrument tokens by exchange and symbol.

type InvalidateTokenUseCase

type InvalidateTokenUseCase struct {
	// contains filtered or unexported fields
}

InvalidateTokenUseCase clears a user's cached Kite access token without touching credentials. Used by the login flow when a cached token is detected as expired against the live Kite API, and by administrative actions (forced re-auth after role change, credential rotation).

Added in Round-5 Phase B to replace direct manager.TokenStore().Delete(email) calls scattered across mcp/setup_tools.go — every cached-token clear now flows through the CommandBus, giving a uniform audit/observability layer for credential lifecycle events.

func NewInvalidateTokenUseCase

func NewInvalidateTokenUseCase(tokenStore TokenStore, logger *slog.Logger) *InvalidateTokenUseCase

NewInvalidateTokenUseCase creates an InvalidateTokenUseCase with the token store injected via the narrow TokenStore port. tokenStore may be nil (tests that construct the use case for behaviour-only coverage); Execute handles that case as a no-op.

func (*InvalidateTokenUseCase) Execute

func (uc *InvalidateTokenUseCase) Execute(ctx context.Context, cmd cqrs.InvalidateTokenCommand) error

Execute clears the cached token for the command's email. Reason is logged at Info level so ops can correlate audit trail entries with the credential-lifecycle narrative (expired vs rotated vs admin-forced).

type KiteCredentialWriter

type KiteCredentialWriter interface {
	SetCredentials(email, apiKey, apiSecret string)
}

KiteCredentialWriter persists per-user Kite API key/secret pairs.

type KiteTokenWriter

type KiteTokenWriter interface {
	SetToken(email, accessToken, userID, userName string)
}

KiteTokenWriter persists Kite access tokens.

type ListAlertsUseCase

type ListAlertsUseCase struct {
	// contains filtered or unexported fields
}

ListAlertsUseCase retrieves all alerts for a user.

func NewListAlertsUseCase

func NewListAlertsUseCase(store AlertReader, logger *slog.Logger) *ListAlertsUseCase

NewListAlertsUseCase creates a ListAlertsUseCase with dependencies injected.

func (*ListAlertsUseCase) Execute

func (uc *ListAlertsUseCase) Execute(ctx context.Context, query cqrs.GetAlertsQuery) ([]*alerts.Alert, error)

Execute retrieves all alerts for the given user.

type ListNativeAlertsUseCase

type ListNativeAlertsUseCase struct {
	// contains filtered or unexported fields
}

ListNativeAlertsUseCase lists all native alerts.

func NewListNativeAlertsUseCase

func NewListNativeAlertsUseCase(logger *slog.Logger) *ListNativeAlertsUseCase

NewListNativeAlertsUseCase creates a ListNativeAlertsUseCase with dependencies injected.

func (*ListNativeAlertsUseCase) Execute

func (uc *ListNativeAlertsUseCase) Execute(ctx context.Context, client NativeAlertClient, query cqrs.ListNativeAlertsQuery) (any, error)

Execute lists native alerts.

type ListTrailingStopsUseCase

type ListTrailingStopsUseCase struct {
	// contains filtered or unexported fields
}

ListTrailingStopsUseCase retrieves all trailing stops for a user.

func NewListTrailingStopsUseCase

func NewListTrailingStopsUseCase(manager TrailingStopManager, logger *slog.Logger) *ListTrailingStopsUseCase

NewListTrailingStopsUseCase creates a ListTrailingStopsUseCase with dependencies injected.

func (*ListTrailingStopsUseCase) Execute

func (uc *ListTrailingStopsUseCase) Execute(ctx context.Context, query cqrs.ListTrailingStopsQuery) ([]*alerts.TrailingStop, error)

Execute retrieves all trailing stops for the user.

type ListWatchlistsUseCase

type ListWatchlistsUseCase struct {
	// contains filtered or unexported fields
}

ListWatchlistsUseCase retrieves all watchlists for a user.

func NewListWatchlistsUseCase

func NewListWatchlistsUseCase(store WatchlistStore, logger *slog.Logger) *ListWatchlistsUseCase

NewListWatchlistsUseCase creates a ListWatchlistsUseCase with dependencies injected.

func (*ListWatchlistsUseCase) Execute

func (uc *ListWatchlistsUseCase) Execute(ctx context.Context, query cqrs.ListWatchlistsQuery) ([]WatchlistInfo, error)

Execute retrieves all watchlists for the given user.

type LoginResult

type LoginResult struct {
	URL string `json:"url"`
}

LoginResult is what LoginUseCase.Execute returns after a successful validation + URL generation. The tool handler is responsible for presentation (the warning banner, markdown link formatting, etc.) and for infrastructure side-effects like opening the browser.

type LoginUseCase

type LoginUseCase struct {
	// contains filtered or unexported fields
}

LoginUseCase validates login command parameters and, given a SessionLoginURLProvider, generates the Kite login URL.

func NewLoginUseCase

func NewLoginUseCase(urls SessionLoginURLProvider, logger *slog.Logger) *LoginUseCase

NewLoginUseCase creates a LoginUseCase with dependencies injected. The SessionLoginURLProvider may be nil for call-sites that only use Validate (e.g. legacy tests); Execute will return an error in that case.

func (*LoginUseCase) Execute

func (uc *LoginUseCase) Execute(ctx context.Context, cmd cqrs.LoginCommand) (*LoginResult, error)

Execute validates the login command and generates the Kite login URL for the given MCP session. Returns the URL wrapped in a LoginResult so the tool handler can format the response and auto-open the browser.

func (*LoginUseCase) Validate

func (uc *LoginUseCase) Validate(_ context.Context, cmd cqrs.LoginCommand) error

Validate checks login command parameters for correctness.

type LotSizeLookup

type LotSizeLookup interface {
	Get(exchange, tradingsymbol string) (lotSize int, tickSize float64, ok bool)
}

LotSizeLookup looks up lot size and tick size for an instrument. Narrow port so the use case does not pull in the full instruments.Manager surface just to check divisibility and tick alignment. Returning ok=false means "metadata unavailable" — the use case treats that as a silent skip rather than a failure, so off-hours or bootstrap paths where instruments aren't loaded keep working.

F5 rename (Phase B/D close-out): was usecases.InstrumentLookup. The old name collided with kc/telegram.InstrumentLookup (different signature: GetByID returning instruments.Instrument) — same name, different contracts. LotSizeLookup captures the actual semantic role of this port: lot/tick-size validation for the order pipeline. Sibling type usecases.InstrumentResolver (token resolution for alerts) stays as-is.

type MetricsAuditReader

type MetricsAuditReader interface {
	GetGlobalStats(since time.Time) (*audit.Stats, error)
	GetToolMetrics(since time.Time) ([]audit.ToolMetric, error)
	GetTopErrorUsers(since time.Time, limit int) ([]audit.UserErrorCount, error)
}

MetricsAuditReader provides read-only query access for audit metrics (ISP-narrowed for observability use cases).

F2 close-out (Phase B/D): renamed from usecases.AuditReader to disambiguate from kc.AuditReader (9-method canonical including per-user List/ListOrders/GetOrderAttribution/GetStats/GetToolCounts/ VerifyChain). The usecases version surfaces only the global-metrics subset that ServerMetricsUseCase actually queries — narrowing keeps the use case's port surface to exactly what it needs.

AuditWriter and AuditStore (the composite) were deleted as part of F2 — both were declared but never referenced as field types or function parameters anywhere in kc/usecases. Pure dead code from an earlier ISP cleanup that didn't follow through to consumers.

*kc.audit.Store satisfies this narrow port structurally — see kc/interfaces.go:127-133 for the wider canonical's matching methods.

type ModifyGTTUseCase

type ModifyGTTUseCase struct {
	// contains filtered or unexported fields
}

ModifyGTTUseCase orchestrates GTT order modification.

func NewModifyGTTUseCase

func NewModifyGTTUseCase(resolver BrokerResolver, logger *slog.Logger) *ModifyGTTUseCase

NewModifyGTTUseCase creates a ModifyGTTUseCase with all dependencies injected.

func (*ModifyGTTUseCase) Execute

func (uc *ModifyGTTUseCase) Execute(ctx context.Context, cmd cqrs.ModifyGTTCommand) (broker.GTTResponse, error)

Execute modifies a GTT order and returns the trigger ID.

func (*ModifyGTTUseCase) SetEventDispatcher

func (uc *ModifyGTTUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so broker failures emit GTTRejectedEvent. Nil-safe.

func (*ModifyGTTUseCase) SetEventStore

func (uc *ModifyGTTUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type ModifyNativeAlertUseCase

type ModifyNativeAlertUseCase struct {
	// contains filtered or unexported fields
}

ModifyNativeAlertUseCase modifies an existing native alert.

func NewModifyNativeAlertUseCase

func NewModifyNativeAlertUseCase(logger *slog.Logger) *ModifyNativeAlertUseCase

NewModifyNativeAlertUseCase creates a ModifyNativeAlertUseCase with dependencies injected.

func (*ModifyNativeAlertUseCase) Execute

func (uc *ModifyNativeAlertUseCase) Execute(ctx context.Context, client NativeAlertClient, cmd cqrs.ModifyNativeAlertCommand) (any, error)

Execute modifies a native alert.

func (*ModifyNativeAlertUseCase) SetEventDispatcher

func (uc *ModifyNativeAlertUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so successful modification emits NativeAlertModifiedEvent. Nil-safe.

func (*ModifyNativeAlertUseCase) SetEventStore

func (uc *ModifyNativeAlertUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type ModifyOrderUseCase

type ModifyOrderUseCase struct {
	// contains filtered or unexported fields
}

ModifyOrderUseCase orchestrates the order modification pipeline: riskguard check -> broker API call -> domain event dispatch.

Wave D Phase 3 Package 5 (Logger sweep): logger is typed as the kc/logger.Logger port. NewModifyOrderUseCase takes *slog.Logger for caller compatibility and converts via logport.NewSlog. Execute uses ctx; helpers use context.Background().

func NewModifyOrderUseCase

func NewModifyOrderUseCase(
	resolver BrokerResolver,
	guard *riskguard.Guard,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *ModifyOrderUseCase

NewModifyOrderUseCase creates a ModifyOrderUseCase with all dependencies injected.

func (*ModifyOrderUseCase) Execute

func (uc *ModifyOrderUseCase) Execute(ctx context.Context, cmd cqrs.ModifyOrderCommand) (broker.OrderResponse, error)

Execute runs the ModifyOrder pipeline and returns the broker response.

func (*ModifyOrderUseCase) SetEventDispatcher

func (uc *ModifyOrderUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher updates the domain event dispatcher post-construction. See PlaceOrderUseCase.SetEventDispatcher for the rationale (production wiring sets the dispatcher after the use case has already been built; without this setter the OrderModifiedEvent emission silently drops).

func (*ModifyOrderUseCase) SetEventStore

func (uc *ModifyOrderUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. Phase C ES.

type NativeAlertClient

type NativeAlertClient interface {
	CreateAlert(params any) (any, error)
	ModifyAlert(uuid string, params any) (any, error)
	DeleteAlerts(uuids ...string) error
	GetAlerts(filters map[string]string) (any, error)
	GetAlertHistory(uuid string) (any, error)
}

NativeAlertClient abstracts the Kite alert API for use cases.

type OAuthClientStore

type OAuthClientStore interface {
	SaveClient(clientID, clientSecret, redirectURIsJSON, clientName string, createdAt time.Time, isKiteKey bool) error
	DeleteClient(clientID string) error
}

OAuthClientStore persists OAuth dynamic-client registrations.

type OpenDashboardUseCase

type OpenDashboardUseCase struct {
	// contains filtered or unexported fields
}

OpenDashboardUseCase validates dashboard page requests.

func NewOpenDashboardUseCase

func NewOpenDashboardUseCase(logger *slog.Logger) *OpenDashboardUseCase

NewOpenDashboardUseCase creates an OpenDashboardUseCase with dependencies injected.

func (*OpenDashboardUseCase) Validate

func (uc *OpenDashboardUseCase) Validate(_ context.Context, query cqrs.OpenDashboardQuery) error

Validate checks that the dashboard query is valid.

type OptionInstrument

type OptionInstrument struct {
	Tradingsymbol string
	Underlying    string // e.g. "NIFTY"
	OptionType    string // "CE" or "PE"
	Strike        float64
	Expiry        string // YYYY-MM-DD prefix match
	LotSize       int
}

OptionInstrument is the slim instrument projection that the options strategy use case needs: enough to resolve a tradingsymbol from (underlying, type, strike, expiry) and to know the lot size.

Mirrors fields from kc/instruments.Instrument but kept local to kc/usecases to avoid cross-module coupling — the adapter that implements OptionInstrumentLookup against the real instruments.Manager is wired at composition root (app/wire.go) where both packages are already imported.

type OptionInstrumentLookup

type OptionInstrumentLookup interface {
	FindOption(underlying, optionType string, strike float64, expiry string) (OptionInstrument, bool)
	DefaultLotSize(underlying string) (int, bool)
}

OptionInstrumentLookup is the narrow port the use case needs for option-instrument resolution. Two methods cover the strategy build:

  • FindOption: get the tradingsymbol + lot size for a (underlying, type, strike, expiry) tuple
  • DefaultLotSize: get a fallback lot size when the user hasn't overridden it (uses the first matching option for the underlying)

F5 rename precedent: same package already has LotSizeLookup (lot/tick metadata) and InstrumentResolver (token resolution). This is a third narrow port for option-specific lookup; intentionally distinct from the others to keep the use case dependencies narrow.

type PaperEngine

type PaperEngine interface {
	Enable(email string, initialCash float64) error
	Disable(email string) error
	Reset(email string) error
	Status(email string) (map[string]any, error)
}

PaperEngine abstracts the paper trading engine for use cases.

type PaperTradeExporter

type PaperTradeExporter interface {
	ExportPaperTrades(email string) ([]any, error)
}

PaperTradeExporter retrieves paper-trading state for the user.

type PaperTradingResetUseCase

type PaperTradingResetUseCase struct {
	// contains filtered or unexported fields
}

PaperTradingResetUseCase resets the virtual portfolio.

func NewPaperTradingResetUseCase

func NewPaperTradingResetUseCase(engine PaperEngine, logger *slog.Logger) *PaperTradingResetUseCase

NewPaperTradingResetUseCase creates a PaperTradingResetUseCase with dependencies injected.

func (*PaperTradingResetUseCase) Execute

func (uc *PaperTradingResetUseCase) Execute(ctx context.Context, cmd cqrs.PaperTradingResetCommand) error

Execute resets the paper trading portfolio.

func (*PaperTradingResetUseCase) SetEventDispatcher

func (uc *PaperTradingResetUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so successful reset emits PaperTradingResetEvent. Nil-safe.

func (*PaperTradingResetUseCase) SetEventStore

func (uc *PaperTradingResetUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type PaperTradingStatusUseCase

type PaperTradingStatusUseCase struct {
	// contains filtered or unexported fields
}

PaperTradingStatusUseCase retrieves paper trading status.

func NewPaperTradingStatusUseCase

func NewPaperTradingStatusUseCase(engine PaperEngine, logger *slog.Logger) *PaperTradingStatusUseCase

NewPaperTradingStatusUseCase creates a PaperTradingStatusUseCase with dependencies injected.

func (*PaperTradingStatusUseCase) Execute

func (uc *PaperTradingStatusUseCase) Execute(ctx context.Context, query cqrs.PaperTradingStatusQuery) (map[string]any, error)

Execute retrieves the paper trading status.

type PaperTradingToggleUseCase

type PaperTradingToggleUseCase struct {
	// contains filtered or unexported fields
}

PaperTradingToggleUseCase enables or disables paper trading mode.

func NewPaperTradingToggleUseCase

func NewPaperTradingToggleUseCase(engine PaperEngine, logger *slog.Logger) *PaperTradingToggleUseCase

NewPaperTradingToggleUseCase creates a PaperTradingToggleUseCase with dependencies injected.

func (*PaperTradingToggleUseCase) Execute

func (uc *PaperTradingToggleUseCase) Execute(ctx context.Context, cmd cqrs.PaperTradingToggleCommand) (string, error)

Execute enables or disables paper trading.

func (*PaperTradingToggleUseCase) SetEventDispatcher

func (uc *PaperTradingToggleUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so successful enable/disable emits PaperTradingEnabledEvent or PaperTradingDisabledEvent. Nil-safe.

func (*PaperTradingToggleUseCase) SetEventStore

func (uc *PaperTradingToggleUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type PlaceGTTUseCase

type PlaceGTTUseCase struct {
	// contains filtered or unexported fields
}

PlaceGTTUseCase orchestrates GTT order placement.

func NewPlaceGTTUseCase

func NewPlaceGTTUseCase(resolver BrokerResolver, logger *slog.Logger) *PlaceGTTUseCase

NewPlaceGTTUseCase creates a PlaceGTTUseCase with all dependencies injected.

func (*PlaceGTTUseCase) Execute

func (uc *PlaceGTTUseCase) Execute(ctx context.Context, cmd cqrs.PlaceGTTCommand) (broker.GTTResponse, error)

Execute places a GTT order and returns the trigger ID.

func (*PlaceGTTUseCase) SetEventDispatcher

func (uc *PlaceGTTUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so broker failures emit GTTRejectedEvent. Nil-safe.

func (*PlaceGTTUseCase) SetEventStore

func (uc *PlaceGTTUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type PlaceMFOrderUseCase

type PlaceMFOrderUseCase struct {
	// contains filtered or unexported fields
}

PlaceMFOrderUseCase places a mutual fund order.

func NewPlaceMFOrderUseCase

func NewPlaceMFOrderUseCase(resolver BrokerResolver, logger *slog.Logger) *PlaceMFOrderUseCase

func (*PlaceMFOrderUseCase) Execute

func (uc *PlaceMFOrderUseCase) Execute(ctx context.Context, cmd cqrs.PlaceMFOrderCommand) (broker.MFOrderResponse, error)

func (*PlaceMFOrderUseCase) SetEventDispatcher

func (uc *PlaceMFOrderUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so broker failures emit MFOrderRejectedEvent. Nil-safe.

func (*PlaceMFOrderUseCase) SetEventStore

func (uc *PlaceMFOrderUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type PlaceMFSIPUseCase

type PlaceMFSIPUseCase struct {
	// contains filtered or unexported fields
}

PlaceMFSIPUseCase places a new mutual fund SIP.

func NewPlaceMFSIPUseCase

func NewPlaceMFSIPUseCase(resolver BrokerResolver, logger *slog.Logger) *PlaceMFSIPUseCase

func (*PlaceMFSIPUseCase) Execute

func (uc *PlaceMFSIPUseCase) Execute(ctx context.Context, cmd cqrs.PlaceMFSIPCommand) (broker.MFSIPResponse, error)

func (*PlaceMFSIPUseCase) SetEventDispatcher

func (uc *PlaceMFSIPUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so broker failures emit MFOrderRejectedEvent. Nil-safe.

func (*PlaceMFSIPUseCase) SetEventStore

func (uc *PlaceMFSIPUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type PlaceNativeAlertUseCase

type PlaceNativeAlertUseCase struct {
	// contains filtered or unexported fields
}

PlaceNativeAlertUseCase creates a server-side alert at Zerodha.

func NewPlaceNativeAlertUseCase

func NewPlaceNativeAlertUseCase(logger *slog.Logger) *PlaceNativeAlertUseCase

NewPlaceNativeAlertUseCase creates a PlaceNativeAlertUseCase with dependencies injected.

func (*PlaceNativeAlertUseCase) Execute

func (uc *PlaceNativeAlertUseCase) Execute(ctx context.Context, client NativeAlertClient, cmd cqrs.PlaceNativeAlertCommand) (any, error)

Execute creates a native alert via the provided client.

func (*PlaceNativeAlertUseCase) SetEventDispatcher

func (uc *PlaceNativeAlertUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so successful placement emits NativeAlertPlacedEvent. Nil-safe.

func (*PlaceNativeAlertUseCase) SetEventStore

func (uc *PlaceNativeAlertUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type PlaceOrderUseCase

type PlaceOrderUseCase struct {
	// contains filtered or unexported fields
}

PlaceOrderUseCase orchestrates the full order placement pipeline: riskguard check -> broker API call -> domain event dispatch.

Wave D Phase 3 Package 5 (Logger sweep): logger is typed as the kc/logger.Logger port. NewPlaceOrderUseCase takes *slog.Logger for caller compatibility (kc/manager_init.go) and converts at the boundary via logport.NewSlog. Internal log calls in Execute use the passed ctx; helpers without ctx use context.Background().

func NewPlaceOrderUseCase

func NewPlaceOrderUseCase(
	resolver BrokerResolver,
	guard *riskguard.Guard,
	events *domain.EventDispatcher,
	logger *slog.Logger,
) *PlaceOrderUseCase

NewPlaceOrderUseCase creates a PlaceOrderUseCase with all dependencies injected.

func (*PlaceOrderUseCase) Execute

func (uc *PlaceOrderUseCase) Execute(ctx context.Context, cmd cqrs.PlaceOrderCommand) (string, error)

Execute runs the PlaceOrder pipeline and returns the broker-assigned order ID.

func (*PlaceOrderUseCase) SetEventDispatcher

func (uc *PlaceOrderUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher updates the domain event dispatcher post-construction. Required because production wiring (app/wire.go) constructs the dispatcher AFTER kc.NewWithOptions returns and pushes it through kcManager.SetEventDispatcher → EventingService.SetDispatcher. Without this propagation, a startup-once-constructed PlaceOrderUseCase would capture a nil dispatcher and silently drop OrderPlacedEvent / OrderFailedEvent emissions. Nil-safe — passing nil disables event dispatch.

func (*PlaceOrderUseCase) SetEventStore

func (uc *PlaceOrderUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. When set, Execute appends an order.placed StoredEvent directly after broker success. Phase C event sourcing — avoids double-emit with the dispatcher→persister path (wire.go drops order.placed persister subscription). The dispatcher path still drives fill_watcher and the Projector. Nil-safe.

func (*PlaceOrderUseCase) SetLotSizeLookup

func (uc *PlaceOrderUseCase) SetLotSizeLookup(l LotSizeLookup)

SetLotSizeLookup wires the lot/tick-size metadata lookup so Execute can enforce lot-size divisibility and tick-size alignment at the domain boundary via domain.InstrumentRules. Nil-safe — when unset, the use case skips lot/tick checks. Optional to avoid breaking callers that construct the use case without instrument metadata (bootstrap, tests).

F5 rename: was SetInstrumentLookup; renamed alongside the LotSizeLookup type for naming consistency with the actual port's semantic role.

type PnLService

type PnLService interface {
	GetJournal(email, fromDate, toDate string) (*alerts.PnLJournalResult, error)
}

PnLService abstracts P&L snapshot retrieval for use cases.

type PortfolioResult

type PortfolioResult struct {
	Holdings  []broker.Holding `json:"holdings"`
	Positions broker.Positions `json:"positions"`
}

PortfolioResult contains the combined holdings and positions for a user.

type PreTradeCheckUseCase

type PreTradeCheckUseCase struct {
	// contains filtered or unexported fields
}

PreTradeCheckUseCase performs pre-trade validation by gathering data from the broker.

func NewPreTradeCheckUseCase

func NewPreTradeCheckUseCase(resolver BrokerResolver, logger *slog.Logger) *PreTradeCheckUseCase

NewPreTradeCheckUseCase creates a PreTradeCheckUseCase with dependencies injected.

func (*PreTradeCheckUseCase) Execute

func (uc *PreTradeCheckUseCase) Execute(ctx context.Context, query cqrs.PreTradeCheckQuery) (*PreTradeData, error)

Execute gathers LTP, margins, positions, holdings, and order margins in parallel.

type PreTradeData

type PreTradeData struct {
	LTP          map[string]broker.LTP `json:"ltp,omitempty"`
	Margins      *broker.Margins       `json:"margins,omitempty"`
	Positions    *broker.Positions     `json:"positions,omitempty"`
	Holdings     []broker.Holding      `json:"holdings,omitempty"`
	OrderMargins any                   `json:"order_margins,omitempty"`
	Errors       map[string]string     `json:"errors,omitempty"`
}

PreTradeData holds the raw data collected from parallel API calls.

type ProvisionUserOnLoginUseCase

type ProvisionUserOnLoginUseCase struct {
	// contains filtered or unexported fields
}

ProvisionUserOnLoginUseCase upserts a user record on first login (or updates the LastLogin timestamp on subsequent logins) and backfills the Kite UID if it was previously empty. Suspended/offboarded users return an error so the caller can fail the login.

func NewProvisionUserOnLoginUseCase

func NewProvisionUserOnLoginUseCase(p UserProvisioner, logger *slog.Logger) *ProvisionUserOnLoginUseCase

NewProvisionUserOnLoginUseCase builds the use case. Passing a nil UserProvisioner is allowed — the use case becomes a no-op (mirrors the dev-mode adapter behaviour).

func (*ProvisionUserOnLoginUseCase) Execute

func (uc *ProvisionUserOnLoginUseCase) Execute(_ context.Context, cmd cqrs.ProvisionUserOnLoginCommand) error

Execute runs the use case.

type RegistryAdminWriter

type RegistryAdminWriter interface {
	Register(id, apiKey, apiSecret, assignedTo, label, status, source, registeredBy string) error
	Update(id, assignedTo, label, status string) error
	Delete(id string) error
}

RegistryAdminWriter abstracts admin-side registry mutations.

type RegistrySync

type RegistrySync interface {
	GetByEmail(email string) (apiKey string, found bool)
	GetByAPIKeyAnyStatus(apiKey string) (assignedTo string, found bool)
	MarkStatus(apiKey, status string)
	Register(id, apiKey, apiSecret, assignedTo, label, status, source, registeredBy string) error
	Update(apiKey, newAssignedTo, label, status string) error
	UpdateLastUsedAt(apiKey string)
}

RegistrySync is the port for SyncRegistryAfterLogin. Mirrors the few methods kiteExchangerAdapter calls on kc/registry.Store — narrow enough to test with a fake.

Update is keyed by APIKey here (not by registry-internal ID) because the use case identifies rows by APIKey at this layer. The adapter is responsible for translating APIKey → ID.

type RemoveFromWatchlistUseCase

type RemoveFromWatchlistUseCase struct {
	// contains filtered or unexported fields
}

RemoveFromWatchlistUseCase removes an instrument from a watchlist.

func NewRemoveFromWatchlistUseCase

func NewRemoveFromWatchlistUseCase(store WatchlistStore, logger *slog.Logger) *RemoveFromWatchlistUseCase

NewRemoveFromWatchlistUseCase creates a RemoveFromWatchlistUseCase with dependencies injected.

func (*RemoveFromWatchlistUseCase) Execute

func (uc *RemoveFromWatchlistUseCase) Execute(ctx context.Context, cmd cqrs.RemoveFromWatchlistCommand) error

Execute removes an item from a watchlist.

func (*RemoveFromWatchlistUseCase) SetEventDispatcher

func (uc *RemoveFromWatchlistUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the domain event dispatcher for typed WatchlistItemRemovedEvent emission. See CreateWatchlistUseCase SetEventDispatcher for the dispatch-vs-audit rationale. Nil-safe.

func (*RemoveFromWatchlistUseCase) SetEventStore

func (uc *RemoveFromWatchlistUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. Phase C ES.

type RevokeCredentialsUseCase

type RevokeCredentialsUseCase struct {
	// contains filtered or unexported fields
}

RevokeCredentialsUseCase deletes a user's Kite credentials and clears their cached access token. Narrower than DeleteMyAccountUseCase — it does not touch alerts, watchlists, trailing stops, paper trading, or the user's "offboarded" status. Use when the intent is "cut access to Kite" while preserving the rest of the account.

Added for Phase B-Audit task #25 so kc/ops dashboard/admin credential revoke paths can route through the bus without semantically expanding DeleteMyAccountCommand.

func NewRevokeCredentialsUseCase

func NewRevokeCredentialsUseCase(credentialStore CredentialUpdater, tokenStore TokenStore, logger *slog.Logger) *RevokeCredentialsUseCase

NewRevokeCredentialsUseCase creates a RevokeCredentialsUseCase with the credential + token stores injected. Either store may be nil during partial bootstrap; Execute tolerates nil as a no-op for that store so a half-initialized Manager does not panic.

func (*RevokeCredentialsUseCase) Execute

func (uc *RevokeCredentialsUseCase) Execute(ctx context.Context, cmd cqrs.RevokeCredentialsCommand) error

Execute deletes the user's credentials and invalidates the cached token. Reason is logged at Info so the audit trail tags intent (user-initiated vs admin-forced vs rotation).

func (*RevokeCredentialsUseCase) SetEventStore

func (uc *RevokeCredentialsUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. When set, Execute appends a credential.revoked StoredEvent after successful revoke. Phase C-Credentials (#31). Nil-safe.

type RiskGuardService

type RiskGuardService interface {
	GetUserStatus(email string) riskguard.UserStatus
	GetEffectiveLimits(email string) riskguard.UserLimits
	GetGlobalFreezeStatus() riskguard.GlobalFreezeStatus
	IsGloballyFrozen() bool
	Freeze(email, by, reason string)
	Unfreeze(email string)
	FreezeGlobal(by, reason string)
	UnfreezeGlobal()
}

RiskGuardService abstracts riskguard for admin use cases.

type SagaError

type SagaError struct {
	// FailedStep is the Name of the step whose Action returned the
	// triggering error.
	FailedStep string
	// Cause is the error returned by FailedStep's Action.
	Cause error
	// CompensationErrors collects any errors raised while running
	// Compensate on the steps that ran before FailedStep. Empty
	// slice when rollback ran cleanly.
	CompensationErrors []error
}

SagaError aggregates errors from a failed Saga: the original Action error that triggered rollback (Cause), and any errors raised during Compensate calls (CompensationErrors). Both are surfaced so callers can distinguish "rollback succeeded cleanly" from "rollback was itself partial".

func (*SagaError) Error

func (e *SagaError) Error() string

Error returns a human-readable summary of the saga failure.

func (*SagaError) Unwrap

func (e *SagaError) Unwrap() error

Unwrap returns the underlying Cause so errors.Is / errors.As work against the triggering error.

type SagaStep

type SagaStep struct {
	// Name identifies the step in logs and the SagaError. Required.
	Name string
	// Action runs the forward operation. May return an error to
	// trigger rollback of all completed prior steps. Required.
	Action func(ctx context.Context) error
	// Compensate undoes the forward Action. May be nil for steps
	// without a meaningful compensation. Errors are logged but do
	// NOT block subsequent compensations.
	Compensate func(ctx context.Context) error
	// ContinueOnError — if true, an error from Action is logged but
	// does NOT trigger rollback; the saga continues to the next step.
	// Use for steps whose failure is acceptable (best-effort cleanups
	// in DeleteMyAccount: paper-engine reset, watchlist deletion).
	ContinueOnError bool
}

SagaStep is one unit of a multi-step business operation that may need to be rolled back if a later step fails. Each step has a forward Action (run during normal execution) and an optional Compensate (run during rollback, in reverse order).

Compensate is BEST-EFFORT: it is called for any step whose Action ran to completion (with or without success — see ContinueOnError). If Compensate itself returns an error, the error is logged and the next compensation runs anyway. This matches the BASE-style saga semantics described in Garcia-Molina & Salem (1987) and Microsoft's saga pattern guidance — full distributed-transaction ACID is NOT a goal here.

Compensate may be nil for steps that are idempotent or whose effects are intentionally not rolled back (e.g., audit-log appends — auditors want to see the failed attempt).

type SaveOAuthClientUseCase

type SaveOAuthClientUseCase struct {
	// contains filtered or unexported fields
}

SaveOAuthClientUseCase persists an OAuth dynamic-client registration.

func NewSaveOAuthClientUseCase

func NewSaveOAuthClientUseCase(s OAuthClientStore, logger *slog.Logger) *SaveOAuthClientUseCase

NewSaveOAuthClientUseCase builds the use case.

func (*SaveOAuthClientUseCase) Execute

func (uc *SaveOAuthClientUseCase) Execute(_ context.Context, cmd cqrs.SaveOAuthClientCommand) error

Execute runs the use case.

type ServerMetricsResult

type ServerMetricsResult struct {
	Period        string                 `json:"period"`
	Stats         *audit.Stats           `json:"stats"`
	ToolMetrics   []audit.ToolMetric     `json:"tool_metrics"`
	TopErrorUsers []audit.UserErrorCount `json:"top_error_users,omitempty"`
}

ServerMetricsResult holds the structured result of a server metrics query.

type ServerMetricsUseCase

type ServerMetricsUseCase struct {
	// contains filtered or unexported fields
}

ServerMetricsUseCase retrieves server observability metrics.

func NewServerMetricsUseCase

func NewServerMetricsUseCase(store MetricsAuditReader, logger *slog.Logger) *ServerMetricsUseCase

NewServerMetricsUseCase creates a ServerMetricsUseCase with dependencies injected.

func (*ServerMetricsUseCase) Execute

func (uc *ServerMetricsUseCase) Execute(ctx context.Context, query cqrs.ServerMetricsQuery) (*ServerMetricsResult, error)

Execute retrieves server metrics for the given period.

type SessionDataClearer

type SessionDataClearer interface {
	ClearSessionData(sessionID string) error
}

SessionDataClearer abstracts the session-data clearing operation. Narrow port (one method) so the use case does not pull in the full ports.SessionPort surface just to perform a single lifecycle write. The kc package's SessionService satisfies this natively via its ClearSessionData method, so no adapter is required at the wiring site.

type SessionExporter

type SessionExporter interface {
	ExportSessions(email string) ([]any, error)
	ExportCredentials(email string) ([]any, error)
}

SessionExporter retrieves session/credential metadata. Credentials must already be encrypted-at-rest; the export ships the encrypted blob.

type SessionLoginURLProvider

type SessionLoginURLProvider interface {
	SessionLoginURL(mcpSessionID string) (string, error)
}

SessionLoginURLProvider is the narrow port LoginUseCase needs from the Manager to generate a Kite login URL for a given MCP session. Keeping the dependency narrow matches the batch C adapter pattern and lets the use case own the full validation+URL-generation flow without pulling in Manager internals.

type SessionTerminator

type SessionTerminator interface {
	TerminateByEmail(email string) int
}

SessionTerminator abstracts session termination.

type SetTrailingStopUseCase

type SetTrailingStopUseCase struct {
	// contains filtered or unexported fields
}

SetTrailingStopUseCase creates a new trailing stop-loss.

func NewSetTrailingStopUseCase

func NewSetTrailingStopUseCase(manager TrailingStopManager, logger *slog.Logger) *SetTrailingStopUseCase

NewSetTrailingStopUseCase creates a SetTrailingStopUseCase with dependencies injected.

func (*SetTrailingStopUseCase) Execute

func (uc *SetTrailingStopUseCase) Execute(ctx context.Context, cmd cqrs.SetTrailingStopCommand) (string, error)

Execute creates a trailing stop and returns the ID.

func (*SetTrailingStopUseCase) SetEventDispatcher

func (uc *SetTrailingStopUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the typed domain event dispatcher so successful creation emits TrailingStopSetEvent. Nil-safe — when unset, only the legacy aux-event path runs.

func (*SetTrailingStopUseCase) SetEventStore

func (uc *SetTrailingStopUseCase) SetEventStore(s EventAppender)

SetEventStore opts the use case into event-sourced audit. nil disables.

type SetupTelegramUseCase

type SetupTelegramUseCase struct {
	// contains filtered or unexported fields
}

SetupTelegramUseCase registers a user's Telegram chat ID for notifications.

func NewSetupTelegramUseCase

func NewSetupTelegramUseCase(store TelegramStore, logger *slog.Logger) *SetupTelegramUseCase

NewSetupTelegramUseCase creates a SetupTelegramUseCase with dependencies injected.

func (*SetupTelegramUseCase) Execute

func (uc *SetupTelegramUseCase) Execute(ctx context.Context, cmd cqrs.SetupTelegramCommand) error

Execute registers the Telegram chat ID.

func (*SetupTelegramUseCase) SetEventDispatcher

func (uc *SetupTelegramUseCase) SetEventDispatcher(d *domain.EventDispatcher)

SetEventDispatcher wires the domain event dispatcher so a typed domain.TelegramSubscribedEvent (first-time bind) or domain.TelegramChatBoundEvent (re-bind to a different chat ID) is dispatched on every successful subscription mutation. The dispatcher path is for runtime subscribers (read-side projector, future consumers); audit persistence is handled by the existing LoggingMiddleware on the command bus. Pattern mirrors CreateWatchlistUseCase.SetEventDispatcher (commit aeb3e8c). Nil-safe.

First-time vs re-bind distinction: Execute snapshots GetTelegramChatID BEFORE the Set so it can tell onboarding from rotation. The store mutation is non-transactional with the event dispatch but this check-then-act race is acceptable — worst case a concurrent re-setup emits two Subscribed events, which is still auditor-correct (they describe two distinct lifecycle moments). Same race tolerance as UpdateMyCredentialsUseCase's CredentialRegistered/Rotated split.

type StartTickerUseCase

type StartTickerUseCase struct {
	// contains filtered or unexported fields
}

StartTickerUseCase starts a WebSocket ticker.

func NewStartTickerUseCase

func NewStartTickerUseCase(ticker TickerService, logger *slog.Logger) *StartTickerUseCase

NewStartTickerUseCase creates a StartTickerUseCase with dependencies injected.

func (*StartTickerUseCase) Execute

func (uc *StartTickerUseCase) Execute(ctx context.Context, cmd cqrs.StartTickerCommand) error

Execute starts a ticker for the user.

type StopTickerUseCase

type StopTickerUseCase struct {
	// contains filtered or unexported fields
}

StopTickerUseCase stops a WebSocket ticker.

func NewStopTickerUseCase

func NewStopTickerUseCase(ticker TickerService, logger *slog.Logger) *StopTickerUseCase

NewStopTickerUseCase creates a StopTickerUseCase with dependencies injected.

func (*StopTickerUseCase) Execute

func (uc *StopTickerUseCase) Execute(ctx context.Context, cmd cqrs.StopTickerCommand) error

Execute stops the user's ticker.

type StoreUserKiteCredentialsUseCase

type StoreUserKiteCredentialsUseCase struct {
	// contains filtered or unexported fields
}

StoreUserKiteCredentialsUseCase writes per-user API key/secret to the credential store after a successful bring-your-own-keys login.

func NewStoreUserKiteCredentialsUseCase

func NewStoreUserKiteCredentialsUseCase(c KiteCredentialWriter, logger *slog.Logger) *StoreUserKiteCredentialsUseCase

NewStoreUserKiteCredentialsUseCase builds the use case.

func (*StoreUserKiteCredentialsUseCase) Execute

func (uc *StoreUserKiteCredentialsUseCase) Execute(_ context.Context, cmd cqrs.StoreUserKiteCredentialsCommand) error

Execute runs the use case.

type StrategyLeg

type StrategyLeg struct {
	TradingSymbol string  `json:"tradingsymbol"`
	OptionType    string  `json:"option_type"` // CE or PE
	Strike        float64 `json:"strike"`
	Action        string  `json:"action"` // BUY or SELL
	Lots          int     `json:"lots"`
	Quantity      int     `json:"quantity"`
	Premium       float64 `json:"premium"` // per-share LTP
	TotalPremium  float64 `json:"total_premium"`
}

StrategyLeg is the per-leg projection of an options strategy. JSON tags match the original mcp/trade/strategyLeg shape so the existing MCP tool handler + dashboard data path stay wire-compatible after the refactor (commit 1408871's payoffStrategyLeg consumes this same JSON shape).

type StrategyResponse

type StrategyResponse struct {
	Strategy     string        `json:"strategy"`
	Underlying   string        `json:"underlying"`
	Expiry       string        `json:"expiry"`
	Legs         []StrategyLeg `json:"legs"`
	NetPremium   float64       `json:"net_premium"`
	MaxProfit    string        `json:"max_profit"`
	MaxLoss      string        `json:"max_loss"`
	MaxProfitAmt float64       `json:"max_profit_amt"`
	MaxLossAmt   float64       `json:"max_loss_amt"`
	Breakevens   []float64     `json:"breakevens"`
	RiskReward   string        `json:"risk_reward_ratio"`
	LotSize      int           `json:"lot_size"`
	TotalLots    int           `json:"total_lots"`
}

StrategyResponse is the use case output. JSON tags match the original mcp/trade/strategyResponse shape (wire-compat invariant).

type SubscribeInstrumentsUseCase

type SubscribeInstrumentsUseCase struct {
	// contains filtered or unexported fields
}

SubscribeInstrumentsUseCase subscribes to instrument tick data.

func NewSubscribeInstrumentsUseCase

func NewSubscribeInstrumentsUseCase(ticker TickerService, logger *slog.Logger) *SubscribeInstrumentsUseCase

NewSubscribeInstrumentsUseCase creates a SubscribeInstrumentsUseCase with dependencies injected.

func (*SubscribeInstrumentsUseCase) Execute

func (uc *SubscribeInstrumentsUseCase) Execute(ctx context.Context, cmd cqrs.SubscribeInstrumentsCommand) error

Execute subscribes to instruments.

type SyncRegistryAfterLoginUseCase

type SyncRegistryAfterLoginUseCase struct {
	// contains filtered or unexported fields
}

SyncRegistryAfterLoginUseCase mirrors kiteExchangerAdapter.ExchangeWith Credentials' registry-side bookkeeping behind a port, dispatched as a command. Three behaviors:

  1. AutoRegister=true + APIKey not in registry → new self_provisioned entry
  2. AutoRegister=true + APIKey already exists with a different owner → reassign
  3. Always: stamp LastUsedAt on the current APIKey if non-empty

If the user previously had a different APIKey, that prior entry is marked Replaced so audit trails show the rotation.

func NewSyncRegistryAfterLoginUseCase

func NewSyncRegistryAfterLoginUseCase(r RegistrySync, logger *slog.Logger) *SyncRegistryAfterLoginUseCase

NewSyncRegistryAfterLoginUseCase builds the use case.

func (*SyncRegistryAfterLoginUseCase) Execute

func (uc *SyncRegistryAfterLoginUseCase) Execute(ctx context.Context, cmd cqrs.SyncRegistryAfterLoginCommand) error

Execute runs the use case.

type TelegramStore

type TelegramStore interface {
	SetTelegramChatID(email string, chatID int64)
	GetTelegramChatID(email string) (int64, bool)
}

TelegramStore abstracts Telegram chat ID persistence.

type TickerService

type TickerService interface {
	Start(email, apiKey, accessToken string) error
	Stop(email string) error
	Subscribe(email string, tokens []uint32, mode ticker.Mode) error
	Unsubscribe(email string, tokens []uint32) error
	GetStatus(email string) (*ticker.Status, error)
	IsRunning(email string) bool
}

TickerService abstracts the WebSocket ticker for use cases.

type TickerStatusUseCase

type TickerStatusUseCase struct {
	// contains filtered or unexported fields
}

TickerStatusUseCase retrieves ticker status.

func NewTickerStatusUseCase

func NewTickerStatusUseCase(ticker TickerService, logger *slog.Logger) *TickerStatusUseCase

NewTickerStatusUseCase creates a TickerStatusUseCase with dependencies injected.

func (*TickerStatusUseCase) Execute

func (uc *TickerStatusUseCase) Execute(ctx context.Context, query cqrs.TickerStatusQuery) (*ticker.Status, error)

Execute retrieves the ticker status.

type TokenStore

type TokenStore interface {
	Delete(email string)
}

TokenStore abstracts token persistence for account use cases.

type ToolCallExporter

type ToolCallExporter interface {
	ExportToolCalls(email string, since time.Time) ([]any, error)
}

ToolCallExporter retrieves tool_call rows for the user.

type TradingContextResult

type TradingContextResult struct {
	Margins   *broker.Margins   `json:"margins,omitempty"`
	Positions *broker.Positions `json:"positions,omitempty"`
	Orders    []broker.Order    `json:"orders,omitempty"`
	Holdings  []broker.Holding  `json:"holdings,omitempty"`
	Errors    map[string]string `json:"errors,omitempty"`
}

TradingContextResult holds the unified trading context snapshot.

type TradingContextUseCase

type TradingContextUseCase struct {
	// contains filtered or unexported fields
}

TradingContextUseCase retrieves a unified trading context snapshot.

func NewTradingContextUseCase

func NewTradingContextUseCase(resolver BrokerResolver, logger *slog.Logger) *TradingContextUseCase

NewTradingContextUseCase creates a TradingContextUseCase with dependencies injected.

func (*TradingContextUseCase) Execute

func (uc *TradingContextUseCase) Execute(ctx context.Context, query cqrs.TradingContextQuery) (*TradingContextResult, error)

Execute retrieves margins, positions, orders, and holdings in parallel.

type TrailingStopManager

type TrailingStopManager interface {
	Add(ts *alerts.TrailingStop) (string, error)
	List(email string) []*alerts.TrailingStop
	Cancel(email, id string) error
	CancelByEmail(email string)
}

TrailingStopManager abstracts trailing stop persistence for use cases.

type UnsubscribeInstrumentsUseCase

type UnsubscribeInstrumentsUseCase struct {
	// contains filtered or unexported fields
}

UnsubscribeInstrumentsUseCase removes instrument subscriptions.

func NewUnsubscribeInstrumentsUseCase

func NewUnsubscribeInstrumentsUseCase(ticker TickerService, logger *slog.Logger) *UnsubscribeInstrumentsUseCase

NewUnsubscribeInstrumentsUseCase creates an UnsubscribeInstrumentsUseCase with dependencies injected.

func (*UnsubscribeInstrumentsUseCase) Execute

func (uc *UnsubscribeInstrumentsUseCase) Execute(ctx context.Context, cmd cqrs.UnsubscribeInstrumentsCommand) error

Execute unsubscribes from instruments.

type UpdateMyCredentialsUseCase

type UpdateMyCredentialsUseCase struct {
	// contains filtered or unexported fields
}

UpdateMyCredentialsUseCase updates a user's Kite API credentials.

Round-5 Phase B note: this use case now OWNS the persistence step. The previous version was validation-only and the MCP tool handler called CredentialStore.Set + TokenStore.Delete separately — a CQRS bypass that left the command dispatched without the corresponding write. The command bus is now the single write entry point for credentials.

func NewUpdateMyCredentialsUseCase

func NewUpdateMyCredentialsUseCase(credStore CredentialUpdater, tokenStore TokenStore, logger *slog.Logger) *UpdateMyCredentialsUseCase

NewUpdateMyCredentialsUseCase creates an UpdateMyCredentialsUseCase with dependencies injected.

func (*UpdateMyCredentialsUseCase) Execute

func (uc *UpdateMyCredentialsUseCase) Execute(ctx context.Context, cmd cqrs.UpdateMyCredentialsCommand) error

Execute validates then persists the user's credentials and invalidates the cached token so the next tool call forces re-authentication against the new Kite developer app. Token invalidation is a double-guard — the underlying kc.KiteCredentialStore.Set already fires its own onTokenInvalidate callback when the API key changes — but calling tokenStore.Delete here makes the contract explicit at the use-case boundary and lets tests assert it without reaching into internals.

func (*UpdateMyCredentialsUseCase) SetEventStore

func (uc *UpdateMyCredentialsUseCase) SetEventStore(s EventAppender)

SetEventStore wires the domain audit-log appender. When set, Execute appends either a credential.registered (first-time) or credential.rotated (replacement) StoredEvent after the successful credential write. Phase C-Credentials (#31). Nil-safe.

type UserProvisioner

type UserProvisioner interface {
	GetStatus(email string) string
	EnsureUser(email, kiteUID, displayName, onboardedBy string) UserRecord
	UpdateLastLogin(email string)
	UpdateKiteUID(email, kiteUID string)
}

UserProvisioner is the narrow port the ProvisionUserOnLogin use case needs. Implementations adapt kc/users.Store. EnsureUser is an upsert that returns the canonical record (or nil if the store is misconfigured); the use case uses the returned record to decide whether to backfill the Kite UID.

type UserRecord

type UserRecord interface {
	GetKiteUID() string
}

UserRecord exposes only the fields the bridge use case needs to decide follow-up writes — keeps usecases.UserProvisioner free of the full kc/users.User struct which would create an import cycle.

type WatchlistExporter

type WatchlistExporter interface {
	ExportWatchlists(email string) ([]any, error)
}

WatchlistExporter retrieves watchlists + items for the user.

type WatchlistInfo

type WatchlistInfo struct {
	ID        string `json:"id"`
	Name      string `json:"name"`
	ItemCount int    `json:"item_count"`
	UpdatedAt string `json:"updated_at"`
}

WatchlistInfo holds summary information about a watchlist.

type WatchlistStore

type WatchlistStore interface {
	CreateWatchlist(email, name string) (string, error)
	DeleteWatchlist(email, watchlistID string) error
	DeleteByEmail(email string)
	ListWatchlists(email string) []*watchlist.Watchlist
	FindWatchlistByName(email, name string) *watchlist.Watchlist
	ItemCount(watchlistID string) int
	AddItem(email, watchlistID string, item *watchlist.WatchlistItem) error
	RemoveItem(email, watchlistID, itemID string) error
	GetItems(watchlistID string) []*watchlist.WatchlistItem
	FindItemBySymbol(watchlistID, exchange, tradingsymbol string) *watchlist.WatchlistItem
}

WatchlistStore abstracts watchlist persistence for use cases.

type WidgetActivityResult

type WidgetActivityResult struct {
	Entries    []*audit.ToolCall `json:"entries"`
	Stats      *audit.Stats      `json:"stats"`
	ToolCounts map[string]int    `json:"tool_counts"`
}

WidgetActivityResult is the activity widget data.

type WidgetAlertItem

type WidgetAlertItem struct {
	ID             string  `json:"id"`
	Symbol         string  `json:"tradingsymbol"`
	Exchange       string  `json:"exchange"`
	Direction      string  `json:"direction"`
	TargetPrice    float64 `json:"target_price"`
	CurrentPrice   float64 `json:"current_price,omitempty"`
	DistancePct    float64 `json:"distance_pct,omitempty"`
	CreatedAt      string  `json:"created_at"`
	TriggeredAt    string  `json:"triggered_at,omitempty"`
	TriggeredPrice float64 `json:"triggered_price,omitempty"`
}

WidgetAlertItem is an alert formatted for the alerts widget.

type WidgetAlertStore

type WidgetAlertStore interface {
	List(email string) []*alerts.Alert
}

WidgetAlertStore abstracts alert read operations for widget use cases.

type WidgetAlertsResult

type WidgetAlertsResult struct {
	Active         []WidgetAlertItem `json:"active"`
	Triggered      []WidgetAlertItem `json:"triggered"`
	ActiveCount    int               `json:"active_count"`
	TriggeredCount int               `json:"triggered_count"`
}

WidgetAlertsResult is the alerts widget data.

type WidgetAuditStore

type WidgetAuditStore interface {
	List(email string, opts audit.ListOptions) ([]*audit.ToolCall, int, error)
	GetStats(email string, since time.Time, category string, errorsOnly bool) (*audit.Stats, error)
	GetToolCounts(email string, since time.Time, category string, errorsOnly bool) (map[string]int, error)
	ListOrders(email string, since time.Time) ([]*audit.ToolCall, error)
}

WidgetAuditStore abstracts the audit store methods needed by widget use cases.

type WidgetBrokerClient

type WidgetBrokerClient interface {
	GetHoldings() ([]broker.Holding, error)
	GetPositions() (broker.Positions, error)
	GetOrders() ([]broker.Order, error)
	GetLTP(instruments ...string) (map[string]broker.LTP, error)
}

WidgetBrokerClient abstracts the broker methods needed by widget use cases.

type WidgetHoldingItem

type WidgetHoldingItem struct {
	Symbol    string  `json:"tradingsymbol"`
	Exchange  string  `json:"exchange"`
	Quantity  int     `json:"quantity"`
	AvgPrice  float64 `json:"average_price"`
	LastPrice float64 `json:"last_price"`
	PnL       float64 `json:"pnl"`
	DayChgPct float64 `json:"day_change_percentage"`
}

WidgetHoldingItem is a holding formatted for widget display.

type WidgetOrderEntry

type WidgetOrderEntry struct {
	OrderID        string  `json:"order_id"`
	Symbol         string  `json:"tradingsymbol"`
	Exchange       string  `json:"exchange"`
	Side           string  `json:"transaction_type"`
	OrderType      string  `json:"order_type"`
	Quantity       float64 `json:"quantity"`
	FilledQuantity float64 `json:"filled_quantity"`
	Price          float64 `json:"price"`
	AveragePrice   float64 `json:"average_price"`
	Status         string  `json:"status"`
	PlacedAt       string  `json:"placed_at"`
}

WidgetOrderEntry is an order formatted for the orders widget.

type WidgetOrdersResult

type WidgetOrdersResult struct {
	Orders  []WidgetOrderEntry `json:"orders"`
	Summary map[string]any     `json:"summary"`
}

WidgetOrdersResult is the orders widget data.

type WidgetPortfolioResult

type WidgetPortfolioResult struct {
	Holdings  []WidgetHoldingItem  `json:"holdings"`
	Positions []WidgetPositionItem `json:"positions"`
	Summary   map[string]any       `json:"summary"`
}

WidgetPortfolioResult is the portfolio widget data.

type WidgetPositionItem

type WidgetPositionItem struct {
	Symbol    string  `json:"tradingsymbol"`
	Exchange  string  `json:"exchange"`
	Quantity  int     `json:"quantity"`
	AvgPrice  float64 `json:"average_price"`
	LastPrice float64 `json:"last_price"`
	PnL       float64 `json:"pnl"`
	Product   string  `json:"product"`
}

WidgetPositionItem is a position formatted for widget display.

type WithdrawConsentResult

type WithdrawConsentResult struct {
	EmailHash       string `json:"email_hash"`
	GrantsWithdrawn int64  `json:"grants_withdrawn"`
}

WithdrawConsentResult carries the outcome of a successful Execute. GrantsWithdrawn is the count of active-grant rows that got stamped. Zero is a normal outcome (user had nothing to withdraw); the caller can decide whether to surface it.

type WithdrawConsentUseCase

type WithdrawConsentUseCase struct {
	// contains filtered or unexported fields
}

WithdrawConsentUseCase orchestrates DPDP §6(4) consent withdrawal: validate input, hash email, stamp consent_log, dispatch event.

func NewWithdrawConsentUseCase

func NewWithdrawConsentUseCase(
	w ConsentWithdrawer,
	h EmailHasher,
	d EventDispatcherPort,
	logger *slog.Logger,
) *WithdrawConsentUseCase

NewWithdrawConsentUseCase builds the use case. dispatcher may be nil.

func (*WithdrawConsentUseCase) Execute

func (uc *WithdrawConsentUseCase) Execute(ctx context.Context, cmd cqrs.WithdrawConsentCommand) (*WithdrawConsentResult, error)

Execute runs the withdrawal. Order:

  1. Validate non-empty email.
  2. Hash via the wired EmailHasher.
  3. Mark consent_log rows withdrawn (port call).
  4. Dispatch ConsentWithdrawnEvent (best-effort; nil dispatcher = skip).

Returns the count of grants that were marked withdrawn so callers can distinguish "first-time withdrawal" from "no-op repeat".

func (*WithdrawConsentUseCase) SetClock

func (uc *WithdrawConsentUseCase) SetClock(now func() time.Time)

SetClock overrides the time source. Tests use this to assert exact withdrawn_at timestamps.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL