main
md 194 lines 8.63 KB
Rendered Raw
1 # ICICI Direct controlled DEV read-only validation
2
3 This runbook prepares and performs the first operator-controlled Breeze DEV authentication. It must not be used for orders, portfolio import, automated OTP handling, or unattended authentication.
4
5 ## Preconditions
6
7 - Use an authenticated DEV application user and the API gateway URL.
8 - Obtain the registered Breeze AppKey, secret key, and registered redirect URL outside Git and chat tooling.
9 - Never enter the ICICI password or OTP anywhere except the official ICICI/Breeze page.
10 - Do not run the portfolio import endpoint during this procedure.
11
12 ## 1. Create the Kubernetes credential Secret without command-line literals
13
14 Run in an interactive PowerShell window. Values are read without echo, converted only in memory, and sent to Kubernetes over stdin. The command prints only Kubernetes resource status.
15
16 ```powershell
17 $Namespace = '<dev-namespace>'
18 $CredentialSecretName = 'aip-icici-direct-dev'
19 $AppKeySecure = Read-Host 'Breeze AppKey' -AsSecureString
20 $SecretKeySecure = Read-Host 'Breeze secret key' -AsSecureString
21 $appKeyPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($AppKeySecure)
22 $secretKeyPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecretKeySecure)
23 try {
24 $appKeyPlain = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($appKeyPointer)
25 $secretKeyPlain = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($secretKeyPointer)
26 $secretManifest = @{
27 apiVersion = 'v1'
28 kind = 'Secret'
29 metadata = @{ name = $CredentialSecretName; namespace = $Namespace }
30 type = 'Opaque'
31 data = @{
32 'app-key' = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($appKeyPlain))
33 'secret-key' = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($secretKeyPlain))
34 }
35 } | ConvertTo-Json -Depth 6 -Compress
36 $secretManifest | kubectl apply -f -
37 } finally {
38 [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($appKeyPointer)
39 [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($secretKeyPointer)
40 Remove-Variable appKeyPlain, secretKeyPlain, secretManifest, AppKeySecure, SecretKeySecure -ErrorAction SilentlyContinue
41 }
42 ```
43
44 Do not use `kubectl get secret ... -o yaml/json`, `kubectl describe secret`, or shell command-line literals containing either credential.
45
46 ## 2. Deploy broker-service configuration
47
48 Create an uncommitted local Helm override containing no credentials:
49
50 ```yaml
51 iciciDirect:
52 enabled: true
53 officialDocumentationVerified: true
54 redirectUrl: "<exact redirect URL registered for the Breeze app>"
55 credentialSecretName: aip-icici-direct-dev
56 ```
57
58 The chart supplies these verified constants:
59
60 - base URL: `https://api.icicidirect.com/breezeapi/api/v1/`
61 - login URL: `https://api.icicidirect.com/apiuser/login`
62 - authentication method: `breeze-interactive-session`
63 - secret reference: `ICICI_DIRECT_SECRET_KEY`
64
65 Deploy using the normal DEV Helm upgrade with the repository values, DEV values, and the uncommitted override. Delete the local override afterward. Do not change any `ibkr` values.
66
67 After rollout, confirm only pod readiness. Do not dump the pod environment. Before a session is attached, ICICI must report `AUTHENTICATION_REQUIRED`, never `CONNECTED`.
68
69 ## 3. Obtain a DEV application access token
70
71 Keep the response and token in variables so PowerShell does not render them:
72
73 ```powershell
74 $ApiBase = 'http://localhost:13000'
75 $devLogin = Invoke-RestMethod -Method Post -Uri "$ApiBase/api/v1/auth/dev/login" `
76 -ContentType 'application/json' -Body '{"userKey":"user-a"}'
77 $AuthorizationHeaders = @{ Authorization = "Bearer $($devLogin.accessToken)" }
78 ```
79
80 Do not print `$devLogin`, `$devLogin.accessToken`, or `$AuthorizationHeaders`.
81
82 ## 4. Create the scoped ICICI connection
83
84 ```powershell
85 $connection = Invoke-RestMethod -Method Post `
86 -Uri "$ApiBase/api/v1/broker-connections/ICICI_DIRECT/connect" `
87 -Headers $AuthorizationHeaders
88 $ConnectionId = $connection.connectionId
89 if ($connection.status -ne 'AUTHENTICATION_REQUIRED') { throw 'Unexpected pre-authentication state' }
90 ```
91
92 Reuse an existing ICICI connection owned by the same DEV user instead if appropriate.
93
94 ## 5. Perform interactive Breeze authentication
95
96 Initiate the connection-scoped login:
97
98 ```powershell
99 $login = Invoke-RestMethod -Method Get `
100 -Uri "$ApiBase/api/v1/broker-connections/$ConnectionId/icici-login" `
101 -Headers $AuthorizationHeaders
102 $login.loginUrl
103 ```
104
105 Verify that the URL host is exactly `api.icicidirect.com`, then open it manually. Complete username/password and OTP only on that official page. Obtain `API_Session` according to the verified Breeze flow; do not paste it into a command line or save it in a file.
106
107 Attach it without terminal echo or command-history disclosure:
108
109 ```powershell
110 $ApiSessionSecure = Read-Host 'Breeze API_Session' -AsSecureString
111 $apiSessionPointer = [Runtime.InteropServices.Marshal]::SecureStringToBSTR($ApiSessionSecure)
112 try {
113 $apiSessionPlain = [Runtime.InteropServices.Marshal]::PtrToStringBSTR($apiSessionPointer)
114 $sessionBody = @{ apiSession = $apiSessionPlain } | ConvertTo-Json -Compress
115 $attached = Invoke-RestMethod -Method Post `
116 -Uri "$ApiBase/api/v1/broker-connections/$ConnectionId/icici-session" `
117 -Headers $AuthorizationHeaders -ContentType 'application/json' -Body $sessionBody
118 } finally {
119 [Runtime.InteropServices.Marshal]::ZeroFreeBSTR($apiSessionPointer)
120 Remove-Variable apiSessionPlain, sessionBody, ApiSessionSecure -ErrorAction SilentlyContinue
121 }
122 if ($attached.status -ne 'CONNECTED') { throw 'Breeze session did not become CONNECTED' }
123 ```
124
125 Do not print `$attached` wholesale. It must not contain session material.
126
127 ## 6. Validate reads in order
128
129 ### Account / Customer Details
130
131 ```powershell
132 $accounts = @(Invoke-RestMethod -Method Get `
133 -Uri "$ApiBase/api/v1/broker-connections/$ConnectionId/accounts" `
134 -Headers $AuthorizationHeaders)
135 $accounts | Select-Object brokerType, status, baseCurrency
136 ```
137
138 Expected: HTTP 200, one normalized `ICICI_DIRECT` account, `ACTIVE`, and `baseCurrency` null. Do not print display name or the masked external reference unnecessarily.
139
140 ### Demat Holdings
141
142 ```powershell
143 $holdings = @(Invoke-RestMethod -Method Get `
144 -Uri "$ApiBase/api/v1/broker-connections/$ConnectionId/demat-holdings" `
145 -Headers $AuthorizationHeaders)
146 $invalidIdentity = @($holdings | Where-Object { $_.instrument.providerInstrumentId -notmatch '^ISIN:[A-Z]{2}[A-Z0-9]{9}[0-9]$' })
147 $fabricated = @($holdings | Where-Object {
148 $null -ne $_.instrument.exchange -or $null -ne $_.instrument.tradingCurrency -or
149 $null -ne $_.averageCost -or $null -ne $_.currentPrice -or
150 $null -ne $_.marketValue -or $null -ne $_.unrealizedProfitLoss
151 })
152 [pscustomobject]@{
153 holdingCount = $holdings.Count
154 invalidIdentityCount = $invalidIdentity.Count
155 fabricatedValuationCount = $fabricated.Count
156 }
157 ```
158
159 Expected: HTTP 200; both error counts zero. Compare quantities privately against broker-visible delivery holdings. Do not publish the complete holdings list.
160
161 ### Funds
162
163 ```powershell
164 $funds = @(Invoke-RestMethod -Method Get `
165 -Uri "$ApiBase/api/v1/broker-connections/$ConnectionId/funds" `
166 -Headers $AuthorizationHeaders)
167 $funds | Select-Object source, @{Name='currency';Expression={$_.cash.currency}}, `
168 @{Name='amountPresent';Expression={$null -ne $_.cash.amount}}, `
169 @{Name='settledCashAbsent';Expression={$null -eq $_.settledCash}}
170 ```
171
172 Expected: HTTP 200, source `BREEZE_FUNDS_TOTAL_BANK_BALANCE`, currency `INR`, amount present, and settled cash absent. Inspect the amount locally only; do not label it settled, withdrawable, or buying power.
173
174 ### Provider capabilities
175
176 ```powershell
177 $providers = @(Invoke-RestMethod -Method Get -Uri "$ApiBase/api/v1/brokers" -Headers $AuthorizationHeaders)
178 $icici = $providers | Where-Object brokerType -eq 'ICICI_DIRECT'
179 $icici | Select-Object status, providerStatus, capabilities, readOnly
180 ```
181
182 Expected connected capabilities: `ACCOUNTS_READ`, `ACCOUNT_METADATA_READ`, `POSITIONS_READ`, and `CASH_READ`. `PORTFOLIO_READ` and `ORDER_EXECUTION` must be absent; `readOnly` must be true.
183
184 ## 7. Stop gate
185
186 Stop after the four validations. Do not call portfolio import, broker sync as a substitute for import, order APIs, Portfolio Holdings, Portfolio Positions, or market-data APIs.
187
188 Current ICICI Demat snapshots are not safe for Phase 5C import: account base currency, instrument exchange/trading currency, average cost, and current price are absent, while the import path and persistence schema require them.
189
190 At the end of the operator session, remove sensitive PowerShell variables:
191
192 ```powershell
193 Remove-Variable devLogin, AuthorizationHeaders, login, attached, accounts, holdings, funds, providers, icici -ErrorAction SilentlyContinue
194 ```