cqrs

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: 8 Imported by: 0

README

kite-mcp-cqrs

Go Reference

CQRS infrastructure (CommandBus + dispatcher + query handlers) for the algo2go ecosystem. Provides in-memory command bus with saga- friendly transaction envelopes and read-side query handlers for orders/holdings/positions/widgets.

Used by Sundeepg98/kite-mcp-server across the manager_commands_* + use case layer for write/read segregation.

Why a separate module?

CQRS is a foundational architectural primitive any algo2go consumer that needs explicit read/write segregation can use independent of kite-mcp-server. Hosting as a module:

  • Centralizes the CommandBus + QueryDispatcher contract
  • Lets command/query interface signatures version independently

Stability promise

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

Install

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

Public API

  • CommandBus — command dispatch with saga-friendly transaction envelopes
  • QueryDispatcher — read-side projection lookup
  • Command/Query interfaces for orders, holdings, positions, widgets

Dependencies

  • github.com/algo2go/kite-mcp-domain v0.1.0
  • github.com/algo2go/kite-mcp-logger v0.1.0
  • github.com/stretchr/testify — assertions

All algo2go deps published; no upstream replace directives needed.

Reference consumer

Sundeepg98/kite-mcp-server — consumed across kc/manager_commands_, kc/manager_queries_, kc/manager_cqrs_register.go, app/wire.go, kc/usecases/, mcp/trade/, mcp/portfolio/, mcp/admin/, mcp/alerts/, mcp/analytics/.

License

MIT — see LICENSE.

Authors

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

Documentation

Overview

Package cqrs provides command and query types for a pragmatic CQRS split.

Commands represent write intentions — they describe what the user wants to change. Queries represent read requests. Both are plain data objects with no behavior. Handler interfaces provide the generic contract for processing commands and queries, enabling testable, composable use-case pipelines.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NativeAlertClientFromContext

func NativeAlertClientFromContext(ctx context.Context) any

NativeAlertClientFromContext returns the NativeAlertClient attached by WithNativeAlertClient, or nil if none was attached.

func WidgetAuditStoreFromContext

func WidgetAuditStoreFromContext(ctx context.Context) any

WidgetAuditStoreFromContext returns the audit store attached by WithWidgetAuditStore, or nil if none was attached.

func WithNativeAlertClient

func WithNativeAlertClient(ctx context.Context, client any) context.Context

WithNativeAlertClient attaches a NativeAlertClient (typed as any to avoid an import cycle with kc/usecases) to the context so the QueryBus handler for ListNativeAlertsQuery / GetNativeAlertHistoryQuery can reach it.

func WithWidgetAuditStore

func WithWidgetAuditStore(ctx context.Context, store any) context.Context

WithWidgetAuditStore attaches an audit store (typed as any to avoid an import cycle with kc/audit) to the context so widget QueryBus handlers can reach a test-scoped store.

Types

type AddToWatchlistCommand

type AddToWatchlistCommand struct {
	Email           string  `json:"email"`
	WatchlistID     string  `json:"watchlist_id"`
	Exchange        string  `json:"exchange"`
	Tradingsymbol   string  `json:"tradingsymbol"`
	InstrumentToken uint32  `json:"instrument_token"`
	Notes           string  `json:"notes,omitempty"`
	TargetEntry     float64 `json:"target_entry,omitempty"`
	TargetExit      float64 `json:"target_exit,omitempty"`
}

AddToWatchlistCommand requests adding an instrument to a watchlist.

type AdminActivateUserCommand

type AdminActivateUserCommand struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
}

AdminActivateUserCommand requests reactivating a user account.

type AdminChangeRoleCommand

type AdminChangeRoleCommand struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
	NewRole     string `json:"new_role"`
}

AdminChangeRoleCommand requests changing a user's role.

type AdminDeleteRegistryCommand

type AdminDeleteRegistryCommand struct {
	ID string `json:"id"`
}

AdminDeleteRegistryCommand requests removing a key-registry entry. Replaces the direct registryStore.Delete call.

type AdminFreezeGlobalCommand

type AdminFreezeGlobalCommand struct {
	AdminEmail string `json:"admin_email"`
	Reason     string `json:"reason"`
}

AdminFreezeGlobalCommand requests freezing all trading globally.

type AdminFreezeUserCommand

type AdminFreezeUserCommand struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
	Reason      string `json:"reason"`
}

AdminFreezeUserCommand requests freezing a user's trading.

type AdminGetRiskStatusQuery

type AdminGetRiskStatusQuery struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
}

AdminGetRiskStatusQuery requests a user's risk status.

type AdminGetUserQuery

type AdminGetUserQuery struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
}

AdminGetUserQuery requests detailed user information.

type AdminInviteFamilyMemberCommand

type AdminInviteFamilyMemberCommand struct {
	AdminEmail   string `json:"admin_email"`
	InvitedEmail string `json:"invited_email"`
}

AdminInviteFamilyMemberCommand requests inviting a family member to share an admin's billing plan. The invited user inherits the admin's tier.

type AdminListFamilyQuery

type AdminListFamilyQuery struct {
	AdminEmail string `json:"admin_email"`
	From       int    `json:"from"`
	Limit      int    `json:"limit"`
}

AdminListFamilyQuery requests the list of family members linked to an admin's billing plan, with pagination.

type AdminListUsersQuery

type AdminListUsersQuery struct {
	AdminEmail string `json:"admin_email"`
	From       int    `json:"from"`
	Limit      int    `json:"limit"`
}

AdminListUsersQuery requests a paginated list of users.

type AdminRegisterAppCommand

type AdminRegisterAppCommand struct {
	ID           string `json:"id"`
	APIKey       string `json:"api_key"`
	APISecret    string `json:"api_secret"`
	AssignedTo   string `json:"assigned_to"`
	Label        string `json:"label"`
	RegisteredBy string `json:"registered_by"` // admin email
}

AdminRegisterAppCommand requests registering a new key-registry entry from the admin dashboard. Source is always admin (vs self-provisioned). Replaces the direct registryStore.Register call in kc/ops/handler_admin.go.

type AdminRemoveFamilyMemberCommand

type AdminRemoveFamilyMemberCommand struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
}

AdminRemoveFamilyMemberCommand requests unlinking a family member from the admin's billing plan. The member loses inherited tier access.

type AdminServerStatusQuery

type AdminServerStatusQuery struct {
	AdminEmail string `json:"admin_email"`
}

AdminServerStatusQuery requests server health overview.

type AdminSuspendUserCommand

type AdminSuspendUserCommand struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
	Reason      string `json:"reason"`
}

AdminSuspendUserCommand requests suspending a user account.

type AdminUnfreezeGlobalCommand

type AdminUnfreezeGlobalCommand struct {
	AdminEmail string `json:"admin_email"`
}

AdminUnfreezeGlobalCommand requests unfreezing global trading.

type AdminUnfreezeUserCommand

type AdminUnfreezeUserCommand struct {
	AdminEmail  string `json:"admin_email"`
	TargetEmail string `json:"target_email"`
}

AdminUnfreezeUserCommand requests unfreezing a user's trading.

type AdminUpdateRegistryCommand

type AdminUpdateRegistryCommand struct {
	ID         string `json:"id"`
	AssignedTo string `json:"assigned_to"`
	Label      string `json:"label"`
	Status     string `json:"status"`
}

AdminUpdateRegistryCommand requests updating an existing key-registry entry's assigned_to / label / status. Replaces the direct registryStore.Update call.

type AlertHistoryResult

type AlertHistoryResult struct {
	AlertID       string               `json:"alert_id"`
	Found         bool                 `json:"found"`
	EventCount    int                  `json:"event_count"`
	FinalStatus   string               `json:"final_status"`
	Email         string               `json:"email,omitempty"`
	Exchange      string               `json:"exchange,omitempty"`
	Tradingsymbol string               `json:"tradingsymbol,omitempty"`
	Direction     string               `json:"direction,omitempty"`
	TargetPrice   float64              `json:"target_price,omitempty"`
	CreatedAt     string               `json:"created_at,omitempty"`
	TriggeredAt   string               `json:"triggered_at,omitempty"`
	DeletedAt     string               `json:"deleted_at,omitempty"`
	Version       int                  `json:"version,omitempty"`
	States        []AlertStateSnapshot `json:"states"`
}

AlertHistoryResult is the read model for GetAlertHistoryReconstitutedQuery.

type AlertStateSnapshot

type AlertStateSnapshot struct {
	Sequence     int64   `json:"sequence"`
	EventType    string  `json:"event_type"`
	OccurredAt   string  `json:"occurred_at"`
	Status       string  `json:"status"`
	TargetPrice  float64 `json:"target_price,omitempty"`
	CurrentPrice float64 `json:"current_price,omitempty"`
}

AlertStateSnapshot captures the alert aggregate at one event-replay step.

type CacheKiteAccessTokenCommand

type CacheKiteAccessTokenCommand struct {
	Email       string `json:"email"`
	AccessToken string `json:"access_token"`
	UserID      string `json:"user_id"`
	UserName    string `json:"user_name"`
}

CacheKiteAccessTokenCommand requests writing a fresh Kite access token to the per-user token cache after a successful OAuth callback. Always keys by lowercased email.

type CancelMFOrderCommand

type CancelMFOrderCommand struct {
	Email   string `json:"email"`
	OrderID string `json:"order_id"`
}

CancelMFOrderCommand requests cancelling a mutual fund order.

type CancelMFSIPCommand

type CancelMFSIPCommand struct {
	Email string `json:"email"`
	SIPID string `json:"sip_id"`
}

CancelMFSIPCommand requests cancelling a mutual fund SIP.

type CancelOrderCommand

type CancelOrderCommand struct {
	Email   string `json:"email"`
	OrderID string `json:"order_id"`
	Variety string `json:"variety,omitempty"`
}

CancelOrderCommand requests cancelling an existing order.

type CancelTrailingStopCommand

type CancelTrailingStopCommand struct {
	Email          string `json:"email"`
	TrailingStopID string `json:"trailing_stop_id"`
}

CancelTrailingStopCommand requests cancelling a trailing stop.

type ClearSessionDataCommand

type ClearSessionDataCommand struct {
	SessionID string `json:"session_id"`
	Reason    string `json:"reason,omitempty"` // "post_credential_register" / "profile_check_failed" / "admin_action"
}

ClearSessionDataCommand requests clearing the Kite session data for an MCP session without terminating the session itself. Used by the login flow when (a) fresh credentials are registered and the next GetOrCreateSession should rebuild the Kite client, or (b) a profile check against Kite fails and the stale Kite-side data must be dropped before a retry.

Round-5 Phase B (Sessions): replaces direct manager.ClearSessionData(id) sites in mcp/setup_tools.go so every session-lifecycle write flows through the command bus, giving a uniform audit/observability layer.

type CloseAllPositionsCommand

type CloseAllPositionsCommand struct {
	Email         string `json:"email"`
	ProductFilter string `json:"product_filter,omitempty"` // MIS/CNC/NRML/ALL
}

CloseAllPositionsCommand requests closing every open position (optionally filtered by product type). Routed through CloseAllPositionsUseCase which applies riskguard per position + dispatches PositionClosedEvent per fill.

type ClosePositionCommand

type ClosePositionCommand struct {
	Email         string `json:"email"`
	Exchange      string `json:"exchange"`
	Symbol        string `json:"symbol"`
	ProductFilter string `json:"product_filter,omitempty"` // MIS/CNC/NRML or empty
}

ClosePositionCommand requests closing a single open position by placing an opposite MARKET order. Routed through ClosePositionUseCase which applies riskguard + dispatches PositionClosedEvent.

type CommandBus

type CommandBus interface {
	// Dispatch sends a command to its handler. Returns error if handler not found
	// or execution fails.
	Dispatch(ctx context.Context, cmd any) error

	// DispatchWithResult sends a command that returns a result (e.g., order ID).
	DispatchWithResult(ctx context.Context, cmd any) (any, error)
}

CommandBus dispatches commands to their registered handlers. All write operations flow through this single entry point.

type CommandHandler

type CommandHandler[C any] interface {
	Handle(ctx context.Context, cmd C) error
}

CommandHandler processes a command of type C and returns an error if the operation fails. Commands are write operations that mutate system state.

Example usage:

type PlaceOrderHandler struct { ... }
func (h *PlaceOrderHandler) Handle(ctx context.Context, cmd PlaceOrderCommand) error { ... }

type CommandHandlerWithResult

type CommandHandlerWithResult[C any, R any] interface {
	Handle(ctx context.Context, cmd C) (R, error)
}

CommandHandlerWithResult processes a command and returns both a result and error. Use this for commands that produce a meaningful return value (e.g., order ID).

Example usage:

type PlaceOrderHandler struct { ... }
func (h *PlaceOrderHandler) Handle(ctx context.Context, cmd PlaceOrderCommand) (string, error) { ... }

type CompositeConditionSpec

type CompositeConditionSpec struct {
	Exchange       string  `json:"exchange"`
	Tradingsymbol  string  `json:"tradingsymbol"`
	Operator       string  `json:"operator"` // above, below, drop_pct, rise_pct
	Value          float64 `json:"value"`
	ReferencePrice float64 `json:"reference_price,omitempty"`
}

CompositeConditionSpec is one leg of a composite alert as it arrives from the MCP tool surface. The spec carries no instrument token — the use case resolves symbols to tokens via the InstrumentResolver so tool handlers can stay agnostic of the instruments store.

type ConvertPositionCommand

type ConvertPositionCommand struct {
	Email           string `json:"email"`
	Exchange        string `json:"exchange"`
	Tradingsymbol   string `json:"tradingsymbol"`
	TransactionType string `json:"transaction_type"`
	Quantity        int    `json:"quantity"`
	OldProduct      string `json:"old_product"`
	NewProduct      string `json:"new_product"`
	PositionType    string `json:"position_type"` // "day" or "overnight"
}

ConvertPositionCommand requests converting a position from one product to another.

type CreateAlertCommand

type CreateAlertCommand struct {
	Email          string  `json:"email"`
	Tradingsymbol  string  `json:"tradingsymbol"`
	Exchange       string  `json:"exchange"`
	TargetPrice    float64 `json:"target_price"`
	Direction      string  `json:"direction"` // above, below, drop_pct, rise_pct
	ReferencePrice float64 `json:"reference_price,omitempty"`
}

CreateAlertCommand requests creating a new price alert.

type CreateCompositeAlertCommand

type CreateCompositeAlertCommand struct {
	Email      string                   `json:"email"`
	Name       string                   `json:"name"`
	Logic      string                   `json:"logic"` // AND or ANY
	Conditions []CompositeConditionSpec `json:"conditions"`
}

CreateCompositeAlertCommand requests creating a composite alert whose conditions are combined by the given logic (AND/ANY). The command is validated in the use case layer — tool handlers should not pre-validate beyond required-field checks.

type CreateWatchlistCommand

type CreateWatchlistCommand struct {
	Email string `json:"email"`
	Name  string `json:"name"`
}

CreateWatchlistCommand requests creating a new named watchlist.

type DeleteAlertCommand

type DeleteAlertCommand struct {
	Email   string `json:"email"`
	AlertID string `json:"alert_id"`
}

DeleteAlertCommand requests deleting an existing alert.

type DeleteGTTCommand

type DeleteGTTCommand struct {
	Email     string `json:"email"`
	TriggerID int    `json:"trigger_id"`
}

DeleteGTTCommand requests deleting an existing GTT order.

type DeleteMyAccountCommand

type DeleteMyAccountCommand struct {
	Email string `json:"email"`
}

DeleteMyAccountCommand requests deleting the authenticated user's account.

type DeleteNativeAlertCommand

type DeleteNativeAlertCommand struct {
	Email string   `json:"email"`
	UUIDs []string `json:"uuids"`
}

DeleteNativeAlertCommand requests deleting native alert(s).

type DeleteOAuthClientCommand

type DeleteOAuthClientCommand struct {
	ClientID string `json:"client_id"`
}

DeleteOAuthClientCommand requests deleting an OAuth dynamic-client registration. Replaces the direct alerts.DB.DeleteClient call.

type DeleteWatchlistCommand

type DeleteWatchlistCommand struct {
	Email       string `json:"email"`
	WatchlistID string `json:"watchlist_id"`
}

DeleteWatchlistCommand requests deleting a watchlist and all its items.

type ExportMyDataCommand

type ExportMyDataCommand struct {
	Email string `json:"email"`
}

ExportMyDataCommand exercises the user's DPDP §11 right to receive a "personal data portability" export of every record we hold under their identity. The use case returns a single JSON document covering tool_calls (5y), alerts, watchlists, paper trades, sessions, credentials (encrypted), consent log, and domain events.

Plaintext email here is intentional — the requester IS the data subject, and §11 is "give me MY data". The use case validates and hashes for internal correlation, then ships plaintext records back.

type FreezeUserCommand

type FreezeUserCommand struct {
	Email    string `json:"email"`
	FrozenBy string `json:"frozen_by"` // "admin", "riskguard:circuit-breaker"
	Reason   string `json:"reason"`
}

FreezeUserCommand requests freezing a user's trading.

type GetActivityForWidgetQuery

type GetActivityForWidgetQuery struct {
	Email string `json:"email"`
	Limit int    `json:"limit,omitempty"`
}

GetActivityForWidgetQuery requests recent audit-trail entries for the activity widget. Limit caps the number of entries returned; when zero, the handler applies the default (20 entries, 7-day window).

type GetAlertHistoryReconstitutedQuery

type GetAlertHistoryReconstitutedQuery struct {
	Email   string `json:"email"`
	AlertID string `json:"alert_id"`
}

GetAlertHistoryReconstitutedQuery requests the full lifecycle of an alert rebuilt from the append-only domain event log. Solves the "did my alert actually fire?" problem when Telegram DMs are dropped — replays AlertCreatedEvent → AlertTriggeredEvent → AlertDeletedEvent to prove delivery independent of the notification layer.

type GetAlertsForWidgetQuery

type GetAlertsForWidgetQuery struct {
	Email string `json:"email"`
}

GetAlertsForWidgetQuery requests alerts enriched with current LTP for the alerts widget.

type GetAlertsQuery

type GetAlertsQuery struct {
	Email string `json:"email"`
}

GetAlertsQuery requests all alerts for a user.

type GetAuditTrailQuery

type GetAuditTrailQuery struct {
	Email      string    `json:"email"`
	Limit      int       `json:"limit,omitempty"`
	Offset     int       `json:"offset,omitempty"`
	Since      time.Time `json:"since,omitempty"`
	OnlyErrors bool      `json:"only_errors,omitempty"`
}

GetAuditTrailQuery requests the tool call audit trail.

type GetBasketMarginsQuery

type GetBasketMarginsQuery struct {
	Email             string                  `json:"email"`
	Orders            []OrderMarginQueryParam `json:"orders"`
	ConsiderPositions bool                    `json:"consider_positions"`
}

GetBasketMarginsQuery requests combined margin for a basket of orders.

type GetGTTsQuery

type GetGTTsQuery struct {
	Email string `json:"email"`
}

GetGTTsQuery requests all GTT orders for a user.

type GetHistoricalDataQuery

type GetHistoricalDataQuery struct {
	Email           string    `json:"email"`
	InstrumentToken int       `json:"instrument_token"`
	Interval        string    `json:"interval"` // minute, 5minute, day, etc.
	From            time.Time `json:"from"`
	To              time.Time `json:"to"`
}

GetHistoricalDataQuery requests historical candle data.

type GetHoldingsQuery

type GetHoldingsQuery struct {
	Email string `json:"email"`
}

GetHoldingsQuery requests only the user's holdings.

type GetLTPQuery

type GetLTPQuery struct {
	Email       string   `json:"email"`
	Instruments []string `json:"instruments"` // "EXCHANGE:SYMBOL" format
}

GetLTPQuery requests the last traded price for instruments.

type GetMFHoldingsQuery

type GetMFHoldingsQuery struct {
	Email string `json:"email"`
}

GetMFHoldingsQuery requests all mutual fund holdings.

type GetMFOrdersQuery

type GetMFOrdersQuery struct {
	Email string `json:"email"`
}

GetMFOrdersQuery requests all mutual fund orders.

type GetMFSIPsQuery

type GetMFSIPsQuery struct {
	Email string `json:"email"`
}

GetMFSIPsQuery requests all mutual fund SIPs.

type GetMarginsQuery

type GetMarginsQuery struct {
	Email string `json:"email"`
}

GetMarginsQuery requests margin/funds information.

type GetNativeAlertHistoryQuery

type GetNativeAlertHistoryQuery struct {
	Email string `json:"email"`
	UUID  string `json:"uuid"`
}

GetNativeAlertHistoryQuery requests trigger history for a native alert.

type GetOHLCQuery

type GetOHLCQuery struct {
	Email       string   `json:"email"`
	Instruments []string `json:"instruments"`
}

GetOHLCQuery requests OHLC data for instruments.

type GetOrderChargesQuery

type GetOrderChargesQuery struct {
	Email  string                   `json:"email"`
	Orders []OrderChargesQueryParam `json:"orders"`
}

GetOrderChargesQuery requests brokerage and charges calculation for orders.

type GetOrderHistoryQuery

type GetOrderHistoryQuery struct {
	Email   string `json:"email"`
	OrderID string `json:"order_id"`
}

GetOrderHistoryQuery requests the state history of a specific order.

type GetOrderHistoryReconstitutedQuery

type GetOrderHistoryReconstitutedQuery struct {
	Email   string `json:"email"`
	OrderID string `json:"order_id"`
}

GetOrderHistoryReconstitutedQuery requests the full lifecycle of an order rebuilt from the append-only domain event log. Unlike GetOrderProjectionQuery (which reads from the in-process Projector, lost on restart) and GetOrderHistoryQuery (which calls the broker API), this query replays the persisted event stream to reconstitute the aggregate — enabling time-travel debugging, corruption recovery, and regulatory audit independent of broker state.

type GetOrderMarginsQuery

type GetOrderMarginsQuery struct {
	Email  string                  `json:"email"`
	Orders []OrderMarginQueryParam `json:"orders"`
}

GetOrderMarginsQuery requests margin calculation for orders.

type GetOrderProjectionQuery

type GetOrderProjectionQuery struct {
	Email   string `json:"email"`
	OrderID string `json:"order_id"`
}

GetOrderProjectionQuery requests the current read-side projection of an order aggregate, built from events dispatched on the domain.EventDispatcher. Unlike GetOrderHistoryQuery (which calls the broker API), this query returns locally-projected state accumulated from in-process domain events.

type GetOrderTradesQuery

type GetOrderTradesQuery struct {
	Email   string `json:"email"`
	OrderID string `json:"order_id"`
}

GetOrderTradesQuery requests executed trades for a specific order.

type GetOrdersForWidgetQuery

type GetOrdersForWidgetQuery struct {
	Email string `json:"email"`
}

GetOrdersForWidgetQuery requests recent order tool-calls enriched with broker status for the orders widget.

type GetOrdersQuery

type GetOrdersQuery struct {
	Email string `json:"email"`
}

GetOrdersQuery requests all orders for the current trading day.

type GetPnLJournalQuery

type GetPnLJournalQuery struct {
	Email    string `json:"email"`
	FromDate string `json:"from_date"`
	ToDate   string `json:"to_date"`
}

GetPnLJournalQuery requests P&L journal data.

type GetPortfolioForWidgetQuery

type GetPortfolioForWidgetQuery struct {
	Email string `json:"email"`
}

GetPortfolioForWidgetQuery requests portfolio data formatted for the portfolio widget (holdings + positions + summary).

type GetPortfolioQuery

type GetPortfolioQuery struct {
	Email string `json:"email"`
}

GetPortfolioQuery requests the user's full portfolio (holdings + positions).

type GetPositionHistoryReconstitutedQuery

type GetPositionHistoryReconstitutedQuery struct {
	Email         string `json:"email"`
	Exchange      string `json:"exchange"`
	Tradingsymbol string `json:"tradingsymbol"`
	Product       string `json:"product"`
}

GetPositionHistoryReconstitutedQuery requests the full open→close lifecycle of a position, keyed by the natural tuple (email, exchange, symbol, product). The event store joins open and close events under the same aggregate via domain.PositionAggregateID(), so a single query returns the complete history — including repeat cycles if the user has opened and closed the same position multiple times.

type GetPositionsQuery

type GetPositionsQuery struct {
	Email string `json:"email"`
}

GetPositionsQuery requests only the user's open positions.

type GetProfileQuery

type GetProfileQuery struct {
	Email string `json:"email"`
}

GetProfileQuery requests the user's broker profile.

type GetQuotesQuery

type GetQuotesQuery struct {
	Email       string   `json:"email"`
	Instruments []string `json:"instruments"` // "EXCHANGE:SYMBOL" format
}

GetQuotesQuery requests full market quotes for instruments.

type GetTradesQuery

type GetTradesQuery struct {
	Email string `json:"email"`
}

GetTradesQuery requests all executed trades for the current trading day.

type GetWatchlistQuery

type GetWatchlistQuery struct {
	Email       string `json:"email"`
	WatchlistID string `json:"watchlist_id"`
}

GetWatchlistQuery requests items in a specific watchlist.

type GetWidgetActivityQuery

type GetWidgetActivityQuery struct {
	Email string `json:"email"`
}

GetWidgetActivityQuery requests activity data formatted for the activity widget.

type GetWidgetAlertsQuery

type GetWidgetAlertsQuery struct {
	Email string `json:"email"`
}

GetWidgetAlertsQuery requests alert data formatted for the alerts widget.

type GetWidgetOrdersQuery

type GetWidgetOrdersQuery struct {
	Email string `json:"email"`
}

GetWidgetOrdersQuery requests order data formatted for the orders widget.

type GetWidgetPortfolioQuery

type GetWidgetPortfolioQuery struct {
	Email string `json:"email"`
}

GetWidgetPortfolioQuery requests portfolio data formatted for the widget.

type HandlerFunc

type HandlerFunc func(ctx context.Context, msg any) (any, error)

HandlerFunc is the generic signature for command/query handlers.

type InMemoryBus

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

InMemoryBus is a synchronous in-process bus that routes commands/queries by Go type to registered handler functions. It implements both CommandBus and QueryBus interfaces.

func NewInMemoryBus

func NewInMemoryBus(middlewares ...Middleware) *InMemoryBus

NewInMemoryBus creates a new bus with optional middleware applied to all dispatches.

func (*InMemoryBus) Dispatch

func (b *InMemoryBus) Dispatch(ctx context.Context, msg any) error

Dispatch routes a message to its handler, applying middleware. Ignores return value.

func (*InMemoryBus) DispatchWithResult

func (b *InMemoryBus) DispatchWithResult(ctx context.Context, msg any) (any, error)

DispatchWithResult routes a message and returns the handler's result.

func (*InMemoryBus) Register

func (b *InMemoryBus) Register(msgType reflect.Type, handler HandlerFunc) error

Register associates a message type with a handler function. Returns an error on duplicate registration so startup code can surface the programmer mistake cleanly instead of crashing the process mid-init.

type InvalidateTokenCommand

type InvalidateTokenCommand struct {
	Email  string `json:"email"`
	Reason string `json:"reason,omitempty"` // "expired" / "credential_rotation" / "admin_action"
}

InvalidateTokenCommand requests clearing the cached Kite access token for the given user. Used by the login flow when a cached token is detected as expired against the live Kite API. Distinct from UpdateMyCredentialsCommand because no new credentials are being written — only the stale token is removed so the next tool call triggers a fresh auth.

type ListNativeAlertsQuery

type ListNativeAlertsQuery struct {
	Email   string            `json:"email"`
	Filters map[string]string `json:"filters,omitempty"`
}

ListNativeAlertsQuery requests native alerts from Zerodha.

type ListTrailingStopsQuery

type ListTrailingStopsQuery struct {
	Email string `json:"email"`
}

ListTrailingStopsQuery requests all trailing stops for a user.

type ListWatchlistsQuery

type ListWatchlistsQuery struct {
	Email string `json:"email"`
}

ListWatchlistsQuery requests all watchlists for a user.

type LoginCommand

type LoginCommand struct {
	Email        string `json:"email"`
	MCPSessionID string `json:"mcp_session_id,omitempty"`
	APIKey       string `json:"api_key,omitempty"`
	APISecret    string `json:"api_secret,omitempty"`
}

LoginCommand requests generating a Kite login URL for the user.

type Middleware

type Middleware func(next HandlerFunc) HandlerFunc

Middleware wraps a handler with cross-cutting concerns.

func LoggingMiddleware

func LoggingMiddleware(logger *slog.Logger) Middleware

LoggingMiddleware logs every dispatch with duration and error status.

Wave D Phase 3 Package 7c-1 (Logger sweep): public signature retains *slog.Logger for backward-compat with all existing callers (app/wire.go, kc/manager.go, tests). Internally wraps via logport.NewSlog so the actual log emission flows through the kc/logger.Logger port with ctx threading.

type ModifyGTTCommand

type ModifyGTTCommand struct {
	Email             string               `json:"email"`
	TriggerID         int                  `json:"trigger_id"`
	Instrument        domain.InstrumentKey `json:"instrument"`
	LastPrice         domain.Money         `json:"last_price"`
	TransactionType   string               `json:"transaction_type"`
	Product           string               `json:"product"`
	Type              string               `json:"type"` // "single" or "two-leg"
	TriggerValue      float64              `json:"trigger_value,omitempty"`
	Quantity          float64              `json:"quantity,omitempty"`
	LimitPrice        domain.Money         `json:"limit_price,omitempty"`
	UpperTriggerValue float64              `json:"upper_trigger_value,omitempty"`
	UpperQuantity     float64              `json:"upper_quantity,omitempty"`
	UpperLimitPrice   domain.Money         `json:"upper_limit_price,omitempty"`
	LowerTriggerValue float64              `json:"lower_trigger_value,omitempty"`
	LowerQuantity     float64              `json:"lower_quantity,omitempty"`
	LowerLimitPrice   domain.Money         `json:"lower_limit_price,omitempty"`
}

ModifyGTTCommand requests modifying an existing GTT order.

type ModifyNativeAlertCommand

type ModifyNativeAlertCommand struct {
	Email  string `json:"email"`
	UUID   string `json:"uuid"`
	Params any    `json:"params"` // kiteconnect.AlertParams
}

ModifyNativeAlertCommand requests modifying a native alert.

type ModifyOrderCommand

type ModifyOrderCommand struct {
	Email            string       `json:"email"`
	OrderID          string       `json:"order_id"`
	Variety          string       `json:"variety,omitempty"`
	Quantity         int          `json:"quantity,omitempty"`
	Price            domain.Money `json:"price,omitempty"`
	TriggerPrice     float64      `json:"trigger_price,omitempty"`
	OrderType        string       `json:"order_type,omitempty"`
	Validity         string       `json:"validity,omitempty"`
	DisclosedQty     int          `json:"disclosed_quantity,omitempty"`
	MarketProtection float64      `json:"market_protection,omitempty"`
	// Confirmed — see PlaceOrderCommand.Confirmed. Satisfies the
	// RequireConfirmAllOrders riskguard gate on re-check.
	Confirmed bool `json:"confirmed,omitempty"`
}

ModifyOrderCommand requests modifying an existing pending order. Price uses domain.Money; Quantity stays int (0 = "don't modify").

type OpenDashboardQuery

type OpenDashboardQuery struct {
	Email string `json:"email"`
	Page  string `json:"page"`
}

OpenDashboardQuery requests a dashboard URL for a specific page.

type OrderChargesQueryParam

type OrderChargesQueryParam struct {
	OrderID         string  `json:"order_id"`
	Exchange        string  `json:"exchange"`
	Tradingsymbol   string  `json:"tradingsymbol"`
	TransactionType string  `json:"transaction_type"`
	Quantity        float64 `json:"quantity"`
	AveragePrice    float64 `json:"average_price"`
	Product         string  `json:"product"`
	OrderType       string  `json:"order_type"`
	Variety         string  `json:"variety"`
}

OrderChargesQueryParam holds parameters for a single order charges calculation.

type OrderHistoryResult

type OrderHistoryResult struct {
	OrderID          string               `json:"order_id"`
	Found            bool                 `json:"found"`
	EventCount       int                  `json:"event_count"`
	FinalStatus      string               `json:"final_status"`
	Email            string               `json:"email,omitempty"`
	Exchange         string               `json:"exchange,omitempty"`
	Tradingsymbol    string               `json:"tradingsymbol,omitempty"`
	TransactionType  string               `json:"transaction_type,omitempty"`
	OrderType        string               `json:"order_type,omitempty"`
	Product          string               `json:"product,omitempty"`
	FinalQuantity    int                  `json:"final_quantity,omitempty"`
	FinalPrice       float64              `json:"final_price,omitempty"`
	FinalFilledPrice float64              `json:"final_filled_price,omitempty"`
	FinalFilledQty   int                  `json:"final_filled_quantity,omitempty"`
	ModifyCount      int                  `json:"modify_count,omitempty"`
	Version          int                  `json:"version,omitempty"`
	PlacedAt         string               `json:"placed_at,omitempty"`
	States           []OrderStateSnapshot `json:"states"`
}

OrderHistoryResult is the read model returned by GetOrderHistoryReconstitutedQuery. Final* fields reflect the state after all events have been applied; States holds one snapshot per event so callers can render the full lifecycle.

type OrderMarginQueryParam

type OrderMarginQueryParam struct {
	Exchange        string  `json:"exchange"`
	Tradingsymbol   string  `json:"tradingsymbol"`
	TransactionType string  `json:"transaction_type"`
	Variety         string  `json:"variety"`
	Product         string  `json:"product"`
	OrderType       string  `json:"order_type"`
	Quantity        float64 `json:"quantity"`
	Price           float64 `json:"price,omitempty"`
	TriggerPrice    float64 `json:"trigger_price,omitempty"`
}

OrderMarginQueryParam holds parameters for a single order margin calculation.

type OrderProjectionResult

type OrderProjectionResult struct {
	OrderID         string  `json:"order_id"`
	Status          string  `json:"status"`
	Email           string  `json:"email"`
	Exchange        string  `json:"exchange"`
	Tradingsymbol   string  `json:"tradingsymbol"`
	TransactionType string  `json:"transaction_type"`
	OrderType       string  `json:"order_type"`
	Product         string  `json:"product"`
	Quantity        int     `json:"quantity"`
	Price           float64 `json:"price"`
	FilledPrice     float64 `json:"filled_price"`
	FilledQuantity  int     `json:"filled_quantity"`
	ModifyCount     int     `json:"modify_count"`
	Version         int     `json:"version"`
	PlacedAt        string  `json:"placed_at,omitempty"`
	ModifiedAt      string  `json:"modified_at,omitempty"`
	CancelledAt     string  `json:"cancelled_at,omitempty"`
	FilledAt        string  `json:"filled_at,omitempty"`
	Found           bool    `json:"found"`
}

OrderProjectionResult is the read model returned by GetOrderProjectionQuery.

type OrderStateSnapshot

type OrderStateSnapshot struct {
	Sequence       int64   `json:"sequence"`
	EventType      string  `json:"event_type"`
	OccurredAt     string  `json:"occurred_at"`
	Status         string  `json:"status"`
	Quantity       int     `json:"quantity"`
	Price          float64 `json:"price"`
	FilledPrice    float64 `json:"filled_price,omitempty"`
	FilledQuantity int     `json:"filled_quantity,omitempty"`
	ModifyCount    int     `json:"modify_count,omitempty"`
}

OrderStateSnapshot captures the order aggregate at one event-replay step. Sequence matches the domain_events.sequence column; EventType identifies which event produced this snapshot (OrderPlaced, OrderModified, etc.).

type PaperTradingResetCommand

type PaperTradingResetCommand struct {
	Email string `json:"email"`
}

PaperTradingResetCommand requests resetting the virtual portfolio.

type PaperTradingStatusQuery

type PaperTradingStatusQuery struct {
	Email string `json:"email"`
}

PaperTradingStatusQuery requests the paper trading status.

type PaperTradingToggleCommand

type PaperTradingToggleCommand struct {
	Email       string  `json:"email"`
	Enable      bool    `json:"enable"`
	InitialCash float64 `json:"initial_cash,omitempty"`
}

PaperTradingToggleCommand requests enabling or disabling paper trading.

type PlaceGTTCommand

type PlaceGTTCommand struct {
	Email             string               `json:"email"`
	Instrument        domain.InstrumentKey `json:"instrument"`
	LastPrice         domain.Money         `json:"last_price"`
	TransactionType   string               `json:"transaction_type"`
	Product           string               `json:"product"`
	Type              string               `json:"type"` // "single" or "two-leg"
	TriggerValue      float64              `json:"trigger_value,omitempty"`
	Quantity          float64              `json:"quantity,omitempty"`
	LimitPrice        domain.Money         `json:"limit_price,omitempty"`
	UpperTriggerValue float64              `json:"upper_trigger_value,omitempty"`
	UpperQuantity     float64              `json:"upper_quantity,omitempty"`
	UpperLimitPrice   domain.Money         `json:"upper_limit_price,omitempty"`
	LowerTriggerValue float64              `json:"lower_trigger_value,omitempty"`
	LowerQuantity     float64              `json:"lower_quantity,omitempty"`
	LowerLimitPrice   domain.Money         `json:"lower_limit_price,omitempty"`
}

PlaceGTTCommand requests placing a new GTT order. Uses domain.InstrumentKey for the instrument and domain.Money for price fields. Quantities remain float64 as the GTT API accepts fractional quantities.

type PlaceMFOrderCommand

type PlaceMFOrderCommand struct {
	Email           string  `json:"email"`
	Tradingsymbol   string  `json:"tradingsymbol"`
	TransactionType string  `json:"transaction_type"`
	Amount          float64 `json:"amount,omitempty"`
	Quantity        float64 `json:"quantity,omitempty"`
	Tag             string  `json:"tag,omitempty"`
}

PlaceMFOrderCommand requests placing a mutual fund order.

type PlaceMFSIPCommand

type PlaceMFSIPCommand struct {
	Email         string  `json:"email"`
	Tradingsymbol string  `json:"tradingsymbol"`
	Amount        float64 `json:"amount"`
	Frequency     string  `json:"frequency"`
	Instalments   int     `json:"instalments"`
	InitialAmount float64 `json:"initial_amount,omitempty"`
	InstalmentDay int     `json:"instalment_day,omitempty"`
	Tag           string  `json:"tag,omitempty"`
}

PlaceMFSIPCommand requests placing a mutual fund SIP.

type PlaceNativeAlertCommand

type PlaceNativeAlertCommand struct {
	Email  string `json:"email"`
	Params any    `json:"params"` // kiteconnect.AlertParams
}

PlaceNativeAlertCommand requests creating a server-side alert at Zerodha.

type PlaceOrderCommand

type PlaceOrderCommand struct {
	Email           string               `json:"email"`
	Instrument      domain.InstrumentKey `json:"instrument"`
	TransactionType string               `json:"transaction_type"` // BUY or SELL
	Qty             domain.Quantity      `json:"qty"`
	Price           domain.Money         `json:"price"`
	OrderType       string               `json:"order_type"` // MARKET, LIMIT, SL, SL-M
	Product         string               `json:"product"`    // CNC, MIS, NRML
	TriggerPrice    float64              `json:"trigger_price,omitempty"`
	Validity        string               `json:"validity,omitempty"`
	Variety         string               `json:"variety,omitempty"`
	Tag             string               `json:"tag,omitempty"`
	// Confirmed signals the user explicitly acknowledged this order (via MCP
	// elicitation or the `confirm: true` tool arg). Threaded down to the
	// riskguard OrderCheckRequest so the default-on RequireConfirmAllOrders
	// gate does not block the dispatched command.
	Confirmed bool `json:"confirmed,omitempty"`
}

PlaceOrderCommand requests placing a new trading order. Uses domain value objects for validated fields: Instrument (exchange+symbol), Qty (positive integer), and Price (Money in INR).

type PositionHistoryResult

type PositionHistoryResult struct {
	AggregateID   string                  `json:"aggregate_id"` // email:exchange:symbol:product
	Found         bool                    `json:"found"`
	EventCount    int                     `json:"event_count"`
	FinalStatus   string                  `json:"final_status"`
	Email         string                  `json:"email,omitempty"`
	Exchange      string                  `json:"exchange,omitempty"`
	Tradingsymbol string                  `json:"tradingsymbol,omitempty"`
	Product       string                  `json:"product,omitempty"`
	OpenedAt      string                  `json:"opened_at,omitempty"`
	ClosedAt      string                  `json:"closed_at,omitempty"`
	States        []PositionStateSnapshot `json:"states"`
}

PositionHistoryResult is the read model for GetPositionHistoryReconstitutedQuery.

type PositionStateSnapshot

type PositionStateSnapshot struct {
	Sequence   int64   `json:"sequence"`
	EventType  string  `json:"event_type"`
	OccurredAt string  `json:"occurred_at"`
	Status     string  `json:"status"`
	Quantity   int     `json:"quantity,omitempty"`
	AvgPrice   float64 `json:"avg_price,omitempty"`
}

PositionStateSnapshot captures the position aggregate at one event-replay step.

type PreTradeCheckQuery

type PreTradeCheckQuery struct {
	Email           string  `json:"email"`
	Exchange        string  `json:"exchange"`
	Tradingsymbol   string  `json:"tradingsymbol"`
	TransactionType string  `json:"transaction_type"`
	Quantity        float64 `json:"quantity"`
	Product         string  `json:"product"`
	OrderType       string  `json:"order_type"`
	Price           float64 `json:"price,omitempty"`
}

PreTradeCheckQuery requests pre-trade validation for a proposed order.

type ProvisionUserOnLoginCommand

type ProvisionUserOnLoginCommand struct {
	Email       string `json:"email"`
	KiteUID     string `json:"kite_uid"`
	DisplayName string `json:"display_name"`
}

ProvisionUserOnLoginCommand requests provisioning a user on first OAuth login (or updating the last-login timestamp on subsequent logins). The handler also fills in the Kite UID if it was previously empty — most users get the UID from Kite's profile call after the very first login.

Returns no error for missing UserStore (single-user / dev mode) — the adapter provisionUser used to be a no-op in that case.

type QueryAuditHook

type QueryAuditHook func(queryType string, email string, durationMs int64, err error)

QueryAuditHook is called after every query use case execution for observability. It receives the query type name, the user email, the execution duration in milliseconds, and any error returned by the query handler.

type QueryBus

type QueryBus interface {
	// Dispatch sends a query to its handler and returns the result.
	Dispatch(ctx context.Context, query any) (any, error)
}

QueryBus dispatches queries to their registered handlers. All read operations flow through this single entry point.

type QueryDispatcher

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

QueryDispatcher provides observability for the read side of CQRS. It accepts audit hooks that are invoked after each query execution, enabling logging, metrics collection, and alerting on slow or failed reads.

Thread-safe: hooks can be added concurrently with Dispatch calls.

Wave D Phase 3 Package 7c-1 (Logger sweep): logger field carries the kc/logger.Logger port. Constructor keeps *slog.Logger for backward- compat with existing callers (app/wire.go, tests) and wraps via logport.NewSlog at the boundary.

func NewQueryDispatcher

func NewQueryDispatcher(logger *slog.Logger) *QueryDispatcher

NewQueryDispatcher creates a QueryDispatcher with the given logger. If logger is nil, error logging is skipped (hooks still fire).

Public signature preserves the *slog.Logger parameter for backward- compat; the value is wrapped via logport.NewSlog so the internal log path uses the typed port.

func (*QueryDispatcher) AddHook

func (d *QueryDispatcher) AddHook(hook QueryAuditHook)

AddHook registers an audit hook that will be called on every Dispatch. Hooks are called in the order they were registered.

func (*QueryDispatcher) Dispatch

func (d *QueryDispatcher) Dispatch(queryType string, email string, durationMs int64, err error)

Dispatch notifies all registered hooks of a completed query execution and logs errors via the configured logger.

type QueryHandler

type QueryHandler[Q any, R any] interface {
	Handle(ctx context.Context, query Q) (R, error)
}

QueryHandler processes a query of type Q and returns a result of type R. Queries are read operations that never mutate system state.

Example usage:

type GetPortfolioHandler struct { ... }
func (h *GetPortfolioHandler) Handle(ctx context.Context, q GetPortfolioQuery) (*Portfolio, error) { ... }

type RemoveFromWatchlistCommand

type RemoveFromWatchlistCommand struct {
	Email       string `json:"email"`
	WatchlistID string `json:"watchlist_id"`
	ItemID      string `json:"item_id"`
}

RemoveFromWatchlistCommand requests removing an instrument from a watchlist.

type RevokeCredentialsCommand

type RevokeCredentialsCommand struct {
	Email  string `json:"email"`
	Reason string `json:"reason,omitempty"`
}

RevokeCredentialsCommand requests deleting the user's Kite credentials and invalidating any cached access token. Narrower than DeleteMyAccountCommand, which also tears down alerts, watchlists, trailing stops, paper trading, and marks the user offboarded.

Use when the intent is strictly "this user can no longer call Kite" — e.g. dashboard credential DELETE, admin force-revoke — while preserving the rest of their account state.

Reason tags the audit trail ("user_self" / "admin_revoke" / "credential_rotation").

type SaveOAuthClientCommand

type SaveOAuthClientCommand struct {
	ClientID         string `json:"client_id"`
	ClientSecret     string `json:"client_secret"`
	RedirectURIsJSON string `json:"redirect_uris_json"`
	ClientName       string `json:"client_name"`
	CreatedAtUnix    int64  `json:"created_at_unix"` // unix nanos so the command is plain data
	IsKiteAPIKey     bool   `json:"is_kite_api_key"`
}

SaveOAuthClientCommand requests persisting an OAuth dynamic-client registration to the alerts DB. Replaces the direct alerts.DB.SaveClient call from clientPersisterAdapter so every write to the OAuth-client table flows through the bus and is logged by LoggingMiddleware.

type ServerMetricsQuery

type ServerMetricsQuery struct {
	AdminEmail string `json:"admin_email"`
	Period     string `json:"period"` // "1h", "24h", "7d", "30d"
}

ServerMetricsQuery requests server observability metrics.

type SetTrailingStopCommand

type SetTrailingStopCommand struct {
	Email           string  `json:"email"`
	Exchange        string  `json:"exchange"`
	Tradingsymbol   string  `json:"tradingsymbol"`
	InstrumentToken uint32  `json:"instrument_token"`
	OrderID         string  `json:"order_id"`
	Variety         string  `json:"variety"`
	Direction       string  `json:"direction"`
	TrailAmount     float64 `json:"trail_amount,omitempty"`
	TrailPct        float64 `json:"trail_pct,omitempty"`
	CurrentStop     float64 `json:"current_stop"`
	ReferencePrice  float64 `json:"reference_price"`
}

SetTrailingStopCommand requests creating a trailing stop-loss.

type SetupTelegramCommand

type SetupTelegramCommand struct {
	Email  string `json:"email"`
	ChatID int64  `json:"chat_id"`
}

SetupTelegramCommand requests registering a user's Telegram chat ID.

type StartTickerCommand

type StartTickerCommand struct {
	Email       string `json:"email"`
	APIKey      string `json:"api_key"`
	AccessToken string `json:"access_token"`
}

StartTickerCommand requests starting a WebSocket ticker.

type StopTickerCommand

type StopTickerCommand struct {
	Email string `json:"email"`
}

StopTickerCommand requests stopping a WebSocket ticker.

type StoreUserKiteCredentialsCommand

type StoreUserKiteCredentialsCommand struct {
	Email     string `json:"email"`
	APIKey    string `json:"api_key"`
	APISecret string `json:"api_secret"`
}

StoreUserKiteCredentialsCommand requests persisting a user's per-user Kite API key/secret (used by the bring-your-own-keys onboarding path).

type SubscribeInstrumentsCommand

type SubscribeInstrumentsCommand struct {
	Email  string   `json:"email"`
	Tokens []uint32 `json:"tokens"`
	Mode   string   `json:"mode"` // "ltp", "quote", "full"
}

SubscribeInstrumentsCommand requests subscribing to live tick data.

type SyncRegistryAfterLoginCommand

type SyncRegistryAfterLoginCommand struct {
	Email     string `json:"email"`
	APIKey    string `json:"api_key"`
	APISecret string `json:"api_secret"` // empty → don't auto-register
	Label     string `json:"label"`      // optional label for new entries
	// AutoRegister controls whether a missing entry should be inserted
	// as self-provisioned. Falsy → only stamp last-used timestamp on
	// existing entries.
	AutoRegister bool `json:"auto_register"`
}

SyncRegistryAfterLoginCommand requests updating the OAuth key registry after a successful login: marks any prior key as Replaced, registers a new self-provisioned entry if missing, reassigns an existing entry to the right owner if needed, and stamps the LastUsedAt timestamp.

PriorKeyHandling: pass empty APISecret/Label to skip the auto-register path (use case for the global-credential branch where we only stamp last-used).

type TickerStatusQuery

type TickerStatusQuery struct {
	Email string `json:"email"`
}

TickerStatusQuery requests the ticker connection status.

type TradingContextQuery

type TradingContextQuery struct {
	Email string `json:"email"`
}

TradingContextQuery requests a unified trading context snapshot.

type UnfreezeUserCommand

type UnfreezeUserCommand struct {
	Email string `json:"email"`
}

UnfreezeUserCommand requests unfreezing a user's trading.

type UnsubscribeInstrumentsCommand

type UnsubscribeInstrumentsCommand struct {
	Email  string   `json:"email"`
	Tokens []uint32 `json:"tokens"`
}

UnsubscribeInstrumentsCommand requests removing instrument subscriptions.

type UpdateMyCredentialsCommand

type UpdateMyCredentialsCommand struct {
	Email     string `json:"email"`
	APIKey    string `json:"api_key"`
	APISecret string `json:"api_secret"`
}

UpdateMyCredentialsCommand requests updating the user's Kite credentials.

type ValidateLoginQuery

type ValidateLoginQuery struct {
	Email     string `json:"email"`
	APIKey    string `json:"api_key,omitempty"`
	APISecret string `json:"api_secret,omitempty"`
}

--- Setup validation queries ---

ValidateLoginQuery is the pre-dispatch validation hop for Login. The real URL-generation path is LoginCommand on the CommandBus; this query exists so the pre-credential-storage validation in setup_tools.go routes through the bus rather than instantiating LoginUseCase directly in the handler. Observability, correlation, and future middleware wrap all bus dispatches uniformly — this closes the last tool-layer escape hatch for Login.

type WithdrawConsentCommand

type WithdrawConsentCommand struct {
	Email         string `json:"email"`
	Reason        string `json:"reason,omitempty"`
	NoticeVersion string `json:"notice_version,omitempty"`
	IPAddress     string `json:"ip_address,omitempty"`
	UserAgent     string `json:"user_agent,omitempty"`
}

WithdrawConsentCommand exercises the user's DPDP §6(4) right to rescind previously-granted consent. The command stamps every active grant in consent_log with withdrawn_at and appends a "withdraw" row describing the action. Reason is plain text recorded for operations; DPDP doesn't require a justification, but operators benefit from having one when correlating with support tickets.

Email is plaintext — the use case hashes it via audit.HashEmail before touching the consent_log so the table never carries the raw address. NoticeVersion identifies which privacy notice is currently in force; the use case records this on the withdraw row as the "version withdrawn from".

Jump to

Keyboard shortcuts

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