@firela/api-types 0.0.0-canary.2fbeefe9 → 0.0.0-canary.30542238

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,7 @@ export const $CreateAccountDto = {
11
11
  openDate: {
12
12
  format: 'date-time',
13
13
  type: 'string',
14
- description: 'Account open date',
14
+ description: 'Account open date (server defaults to today)',
15
15
  example: '2024-01-01'
16
16
  },
17
17
  currencies: {
@@ -51,9 +51,10 @@ export const $CreateAccountDto = {
51
51
  description: 'Icon identifier (overrides template)',
52
52
  example: 'bank-custom'
53
53
  },
54
- openMeta: {
54
+ openDirectiveMeta: {
55
55
  type: 'object',
56
- description: 'Additional metadata',
56
+ description:
57
+ 'Open directive metadata (NOT an opening-balance amount — use the opening-balance endpoint)',
57
58
  example: {
58
59
  branch: 'Downtown',
59
60
  accountNumber: '1234'
@@ -65,7 +66,7 @@ export const $CreateAccountDto = {
65
66
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
66
67
  }
67
68
  },
68
- required: ['path', 'openDate']
69
+ required: ['path']
69
70
  } as const;
70
71
 
71
72
  export const $AccountResponseDto = {
@@ -87,6 +88,49 @@ export const $AccountResponseDto = {
87
88
  enum: ['Assets', 'Liabilities', 'Income', 'Expenses', 'Equity'],
88
89
  example: 'Assets'
89
90
  },
91
+ assetSubClass: {
92
+ type: 'string',
93
+ description:
94
+ 'Account-level asset sub-class (product type, e.g. STOCK/DEPOSIT/CREDIT_CARD/PERSONAL_LOAN). Computed from the account path via the asset-classifier (ADR-0077). Null for non-asset accounts (Income/Expenses/Equity) or unmatched paths.',
95
+ enum: [
96
+ 'DEPOSIT',
97
+ 'CASH',
98
+ 'MONEY_MARKET_FUND',
99
+ 'STOCK',
100
+ 'ETF',
101
+ 'MUTUAL_FUND',
102
+ 'EQUITY_COMPENSATION',
103
+ 'GOVERNMENT_BOND',
104
+ 'CORPORATE_BOND',
105
+ 'BOND_FUND',
106
+ 'PRIMARY_RESIDENCE',
107
+ 'INVESTMENT_PROPERTY',
108
+ 'REIT',
109
+ 'GOLD',
110
+ 'SILVER',
111
+ 'PRECIOUS_METAL',
112
+ 'PRECIOUS_METAL_FUND',
113
+ 'COMMODITY',
114
+ 'COMMODITY_FUND',
115
+ 'CRYPTOCURRENCY',
116
+ 'RETIREMENT_ACCOUNT',
117
+ 'HEALTH_ACCOUNT',
118
+ 'EDUCATION_ACCOUNT',
119
+ 'INSURANCE',
120
+ 'PRIVATE_EQUITY',
121
+ 'HEDGE_FUND',
122
+ 'COLLECTIBLES',
123
+ 'MORTGAGE',
124
+ 'STUDENT_LOAN',
125
+ 'CREDIT_CARD',
126
+ 'PERSONAL_LOAN',
127
+ 'ACCOUNTS_PAYABLE',
128
+ 'TAX_PAYABLE',
129
+ 'OTHER'
130
+ ],
131
+ nullable: true,
132
+ example: 'STOCK'
133
+ },
90
134
  status: {
91
135
  type: 'string',
92
136
  description: 'Account status',
@@ -145,9 +189,9 @@ export const $AccountResponseDto = {
145
189
  description: 'Icon identifier',
146
190
  example: 'bank-icbc'
147
191
  },
148
- openMeta: {
192
+ openDirectiveMeta: {
149
193
  type: 'object',
150
- description: 'Account metadata',
194
+ description: 'Open directive metadata (ADR-0115 Decision 9)',
151
195
  example: {
152
196
  branch: 'Downtown'
153
197
  }
@@ -233,9 +277,10 @@ export const $UpdateAccountDto = {
233
277
  description: 'Icon identifier',
234
278
  example: 'bank-custom'
235
279
  },
236
- openMeta: {
280
+ openDirectiveMeta: {
237
281
  type: 'object',
238
- description: 'Additional metadata (merged with existing)',
282
+ description:
283
+ 'Open directive metadata (merged with existing; NOT an opening-balance amount)',
239
284
  example: {
240
285
  branch: 'Uptown'
241
286
  }
@@ -282,6 +327,40 @@ export const $ReopenAccountDto = {
282
327
  }
283
328
  } as const;
284
329
 
330
+ export const $CreateOpeningBalanceDto = {
331
+ type: 'object',
332
+ properties: {
333
+ amount: {
334
+ type: 'number',
335
+ description: 'Opening balance amount (non-negative)',
336
+ example: 1000
337
+ },
338
+ currency: {
339
+ type: 'string',
340
+ description: 'Currency code',
341
+ example: 'CNY'
342
+ },
343
+ date: {
344
+ format: 'date-time',
345
+ type: 'string',
346
+ description: 'Opening-balance date (defaults to now)',
347
+ example: '2024-01-01'
348
+ }
349
+ },
350
+ required: ['amount', 'currency']
351
+ } as const;
352
+
353
+ export const $OpeningBalanceResultDto = {
354
+ type: 'object',
355
+ properties: {
356
+ transactionId: {
357
+ type: 'string',
358
+ description: 'Created opening-balance transaction id.'
359
+ }
360
+ },
361
+ required: ['transactionId']
362
+ } as const;
363
+
285
364
  export const $AccountStandardResponseDto = {
286
365
  type: 'object',
287
366
  properties: {
@@ -318,9 +397,47 @@ export const $AccountStandardResponseDto = {
318
397
  type: 'string',
319
398
  description: 'Icon identifier for UI display',
320
399
  example: 'bank-icbc'
400
+ },
401
+ productCategory: {
402
+ type: 'string',
403
+ description:
404
+ 'Onboarding product category (coarse grouping derived from assetSubClass)',
405
+ enum: [
406
+ 'cash',
407
+ 'investment',
408
+ 'credit_card',
409
+ 'loan',
410
+ 'payable_tax',
411
+ 'other'
412
+ ],
413
+ example: 'investment'
414
+ },
415
+ assetClass: {
416
+ type: 'string',
417
+ description:
418
+ 'Asset class (LIQUIDITY/EQUITY/.../LIABILITY), derived at read time from classification rules',
419
+ enum: [
420
+ 'LIQUIDITY',
421
+ 'EQUITY',
422
+ 'FIXED_INCOME',
423
+ 'PRECIOUS_METALS',
424
+ 'COMMODITY',
425
+ 'INSURANCE',
426
+ 'ALTERNATIVE_INVESTMENT',
427
+ 'PERSONAL_ASSETS',
428
+ 'LIABILITY',
429
+ 'REAL_ESTATE',
430
+ 'INDEX'
431
+ ]
432
+ },
433
+ assetSubClass: {
434
+ type: 'string',
435
+ description:
436
+ 'Asset sub-class (product type, derived at read time from classification rules)',
437
+ example: 'STOCK'
321
438
  }
322
439
  },
323
- required: ['path', 'type', 'description', 'tags', 'icon']
440
+ required: ['path', 'type', 'description', 'tags', 'icon', 'productCategory']
324
441
  } as const;
325
442
 
326
443
  export const $AccountStandardListResponseDto = {
@@ -659,7 +776,7 @@ export const $PostingResponseDto = {
659
776
  units: {
660
777
  type: 'string',
661
778
  description:
662
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
779
+ 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned. Carries the raw Beancount sign (credit-normal accounts such as Income post negative — the accounting truth, ADR-0126); renderers must not infer economic semantics from this sign.',
663
780
  example: '100.50'
664
781
  },
665
782
  currency: {
@@ -1025,7 +1142,7 @@ export const $PostingDetailDto = {
1025
1142
  units: {
1026
1143
  type: 'string',
1027
1144
  description:
1028
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
1145
+ 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned. Carries the raw Beancount sign (credit-normal accounts such as Income post negative — the accounting truth, ADR-0126); renderers must not infer economic semantics from this sign.',
1029
1146
  example: '100.50'
1030
1147
  },
1031
1148
  currency: {
@@ -1209,6 +1326,147 @@ export const $TransactionDetailDto = {
1209
1326
  ]
1210
1327
  } as const;
1211
1328
 
1329
+ export const $TransactionListItemDto = {
1330
+ type: 'object',
1331
+ properties: {
1332
+ id: {
1333
+ type: 'string',
1334
+ description: 'Transaction ID',
1335
+ example: 'clh1234567890abcdef'
1336
+ },
1337
+ date: {
1338
+ type: 'string',
1339
+ description: 'Transaction date',
1340
+ example: '2024-11-28'
1341
+ },
1342
+ flag: {
1343
+ type: 'string',
1344
+ description: 'Transaction flag',
1345
+ enum: [
1346
+ 'CLEARED',
1347
+ 'PENDING',
1348
+ 'PADDING',
1349
+ 'SUMMARIZE',
1350
+ 'TRANSFER',
1351
+ 'CONVERSIONS'
1352
+ ],
1353
+ example: 'CLEARED'
1354
+ },
1355
+ customFlag: {
1356
+ type: 'string',
1357
+ description: 'Custom flag (if not using standard flags)',
1358
+ example: 'R'
1359
+ },
1360
+ payee: {
1361
+ type: 'string',
1362
+ description: 'Payee name',
1363
+ example: 'Whole Foods Market'
1364
+ },
1365
+ narration: {
1366
+ type: 'string',
1367
+ description: 'Transaction narration',
1368
+ example: 'Grocery shopping'
1369
+ },
1370
+ tags: {
1371
+ description: 'Transaction tags',
1372
+ example: ['groceries'],
1373
+ type: 'array',
1374
+ items: {
1375
+ type: 'string'
1376
+ }
1377
+ },
1378
+ links: {
1379
+ description: 'Transaction links',
1380
+ example: ['invoice-2024-001'],
1381
+ type: 'array',
1382
+ items: {
1383
+ type: 'string'
1384
+ }
1385
+ },
1386
+ meta: {
1387
+ type: 'object',
1388
+ description: 'Transaction metadata'
1389
+ },
1390
+ status: {
1391
+ type: 'string',
1392
+ description: 'Transaction status',
1393
+ enum: ['ACTIVE', 'VOIDED', 'SUPERSEDED'],
1394
+ example: 'ACTIVE'
1395
+ },
1396
+ sourceType: {
1397
+ type: 'string',
1398
+ description:
1399
+ 'Source type (free-form string from transaction metadata, e.g. import, api)'
1400
+ },
1401
+ sourcePlatform: {
1402
+ type: 'string',
1403
+ description: 'Source platform (e.g., alipay, wechat)',
1404
+ example: 'alipay'
1405
+ },
1406
+ postings: {
1407
+ description: 'Transaction postings',
1408
+ type: 'array',
1409
+ items: {
1410
+ $ref: '#/components/schemas/PostingDetailDto'
1411
+ }
1412
+ },
1413
+ createdAt: {
1414
+ type: 'string',
1415
+ description: 'Created at timestamp',
1416
+ example: '2024-11-28T10:30:00.000Z'
1417
+ },
1418
+ voidedAt: {
1419
+ type: 'string',
1420
+ description: 'Voided at timestamp (if voided)',
1421
+ example: '2024-11-29T15:00:00.000Z'
1422
+ },
1423
+ voidedBy: {
1424
+ type: 'string',
1425
+ description: 'User ID who voided this transaction',
1426
+ example: 'clh1234567890abcdef'
1427
+ },
1428
+ correctionReason: {
1429
+ type: 'string',
1430
+ description: 'Correction reason (if voided or superseded)',
1431
+ example: 'Duplicate entry'
1432
+ },
1433
+ supersededBy: {
1434
+ type: 'string',
1435
+ description:
1436
+ 'ID of the transaction that supersedes this one (set when status=SUPERSEDED)',
1437
+ example: 'clh1234567890abcdef'
1438
+ },
1439
+ originalTxn: {
1440
+ type: 'string',
1441
+ description:
1442
+ 'ID of the transaction this one corrected/replaced (back-link on the replacement)',
1443
+ example: 'clh1234567890abcdef'
1444
+ },
1445
+ viewpointAmount: {
1446
+ type: 'string',
1447
+ description:
1448
+ 'Row amount under the request viewpoint (ADR-0126). Category viewpoint (category + flow): per-leg sign-normalized sum over the category account set (Income-root legs negated, Expenses-root identity) — positive under normal booking but NOT clamped (explicit negative expense legs and net-flip refund months stay negative). No viewpoint (plain list / search, no accountId): wallet money-flow net = raw-sign sum over cost-less Assets/Liabilities legs (income positive, expenses negative, transfers net ~0); color cue is the wallet sign (net < 0 = wealth-decreasing). Status-orthogonal: audit views match too (ADR-0128 amount-as-matching-key). Omitted under the account viewpoint (incl. dual) and for rows with no wallet leg.',
1449
+ example: '10000.00'
1450
+ },
1451
+ viewpointCurrency: {
1452
+ type: 'string',
1453
+ description:
1454
+ 'Currency of viewpointAmount. A row spanning multiple currencies takes the largest-magnitude currency group (known simplification, ADR-0126).',
1455
+ example: 'CNY'
1456
+ }
1457
+ },
1458
+ required: [
1459
+ 'id',
1460
+ 'date',
1461
+ 'narration',
1462
+ 'tags',
1463
+ 'links',
1464
+ 'status',
1465
+ 'postings',
1466
+ 'createdAt'
1467
+ ]
1468
+ } as const;
1469
+
1212
1470
  export const $BalanceByCurrencyDto = {
1213
1471
  type: 'object',
1214
1472
  properties: {
@@ -1254,7 +1512,7 @@ export const $TransactionListSummaryDto = {
1254
1512
  totalAmount: {
1255
1513
  type: 'string',
1256
1514
  description:
1257
- 'Partial converted total in base currency (rated currencies only, raw Beancount sign). When warnings is non-empty this excludes currencies missing an FX rate; may be "0.00" if ALL non-base currencies lack a rate. Converted at the dateTo (or current) available rate.',
1515
+ 'Partial converted total in base currency (rated currencies only). Sign by viewpoint (ADR-0126): account viewpoint keeps the raw Beancount sign (income negative); category viewpoint is per-leg sign-normalized (Income legs negated, Expenses legs identity — positive under normal booking, not clamped). When warnings is non-empty this excludes currencies missing an FX rate; may be "0.00" if ALL non-base currencies lack a rate. Converted at the dateTo (or current) available rate.',
1258
1516
  example: '-6000.00'
1259
1517
  },
1260
1518
  currency: {
@@ -1280,6 +1538,26 @@ export const $TransactionListSummaryDto = {
1280
1538
  required: ['totalAmount', 'currency', 'balanceByCurrency']
1281
1539
  } as const;
1282
1540
 
1541
+ export const $TransactionListViewpointDto = {
1542
+ type: 'object',
1543
+ properties: {
1544
+ type: {
1545
+ type: 'string',
1546
+ description:
1547
+ 'Viewpoint type (only category drill-down carries a viewpoint today)',
1548
+ enum: ['category'],
1549
+ example: 'category'
1550
+ },
1551
+ flow: {
1552
+ type: 'string',
1553
+ description: 'Flow root the category account set is restricted to',
1554
+ enum: ['income', 'expense'],
1555
+ example: 'expense'
1556
+ }
1557
+ },
1558
+ required: ['type', 'flow']
1559
+ } as const;
1560
+
1283
1561
  export const $TransactionListResponseDto = {
1284
1562
  type: 'object',
1285
1563
  properties: {
@@ -1287,7 +1565,7 @@ export const $TransactionListResponseDto = {
1287
1565
  description: 'List of transactions',
1288
1566
  type: 'array',
1289
1567
  items: {
1290
- $ref: '#/components/schemas/TransactionDetailDto'
1568
+ $ref: '#/components/schemas/TransactionListItemDto'
1291
1569
  }
1292
1570
  },
1293
1571
  total: {
@@ -1313,6 +1591,15 @@ export const $TransactionListResponseDto = {
1313
1591
  $ref: '#/components/schemas/TransactionListSummaryDto'
1314
1592
  }
1315
1593
  ]
1594
+ },
1595
+ viewpoint: {
1596
+ description:
1597
+ 'Viewpoint metadata (ADR-0126). Present only for a single category filter (category + flow, no accountId); dual-perspective requests are viewpoint-less (raw signs, no viewpointAmount).',
1598
+ allOf: [
1599
+ {
1600
+ $ref: '#/components/schemas/TransactionListViewpointDto'
1601
+ }
1602
+ ]
1316
1603
  }
1317
1604
  },
1318
1605
  required: ['data', 'total', 'limit', 'offset']
@@ -3715,24 +4002,515 @@ export const $ForecastResponseDto = {
3715
4002
  ]
3716
4003
  } as const;
3717
4004
 
3718
- export const $CreateTransactionRuleDto = {
4005
+ export const $CurrencyBalanceDto = {
3719
4006
  type: 'object',
3720
4007
  properties: {
3721
- name: {
4008
+ currency: {
3722
4009
  type: 'string',
3723
- minLength: 1,
3724
- maxLength: 100
4010
+ description: 'ISO 4217 currency code',
4011
+ example: 'CNY'
3725
4012
  },
3726
- description: {
4013
+ balance: {
3727
4014
  type: 'string',
3728
- maxLength: 500
4015
+ description: 'Balance amount',
4016
+ example: '500000.00'
4017
+ }
4018
+ },
4019
+ required: ['currency', 'balance']
4020
+ } as const;
4021
+
4022
+ export const $TimeSeriesPointDto = {
4023
+ type: 'object',
4024
+ properties: {
4025
+ date: {
4026
+ type: 'string',
4027
+ description: 'Date in YYYY-MM-DD format',
4028
+ example: '2024-06-15'
3729
4029
  },
3730
- narrationKeywords: {
3731
- items: {
3732
- type: 'array'
3733
- },
3734
- maxItems: 50,
3735
- type: 'array'
4030
+ value: {
4031
+ type: 'string',
4032
+ description: 'Value at this date (in base currency)',
4033
+ example: '500000.00'
4034
+ },
4035
+ change: {
4036
+ type: 'object',
4037
+ description: 'Change from previous point',
4038
+ example: '5000.00'
4039
+ },
4040
+ assets: {
4041
+ type: 'string',
4042
+ description: 'Total assets at this date (in base currency)',
4043
+ example: '494338.00'
4044
+ },
4045
+ liabilities: {
4046
+ type: 'string',
4047
+ description: 'Total liabilities at this date (in base currency)',
4048
+ example: '310098.00'
4049
+ },
4050
+ byCurrency: {
4051
+ description: 'Multi-currency breakdown for this point',
4052
+ type: 'array',
4053
+ items: {
4054
+ $ref: '#/components/schemas/CurrencyBalanceDto'
4055
+ }
4056
+ }
4057
+ },
4058
+ required: ['date', 'value']
4059
+ } as const;
4060
+
4061
+ export const $TrendSummaryDto = {
4062
+ type: 'object',
4063
+ properties: {
4064
+ startValue: {
4065
+ type: 'string',
4066
+ description: 'Value at start of period',
4067
+ example: '450000.00'
4068
+ },
4069
+ endValue: {
4070
+ type: 'string',
4071
+ description: 'Value at end of period',
4072
+ example: '500000.00'
4073
+ },
4074
+ totalChange: {
4075
+ type: 'string',
4076
+ description: 'Total change over period',
4077
+ example: '50000.00'
4078
+ },
4079
+ totalChangePercentage: {
4080
+ type: 'string',
4081
+ description: 'Total change percentage',
4082
+ example: '+11.11%'
4083
+ }
4084
+ },
4085
+ required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
4086
+ } as const;
4087
+
4088
+ export const $MultiCurrencyPointDto = {
4089
+ type: 'object',
4090
+ properties: {
4091
+ date: {
4092
+ type: 'string',
4093
+ description: 'Date in YYYY-MM-DD format',
4094
+ example: '2024-06-15'
4095
+ },
4096
+ byCurrency: {
4097
+ description: 'Balances by currency',
4098
+ type: 'array',
4099
+ items: {
4100
+ $ref: '#/components/schemas/CurrencyBalanceDto'
4101
+ }
4102
+ }
4103
+ },
4104
+ required: ['date', 'byCurrency']
4105
+ } as const;
4106
+
4107
+ export const $PortfolioTrendsResponseDto = {
4108
+ type: 'object',
4109
+ properties: {
4110
+ series: {
4111
+ description: 'Time series data points',
4112
+ type: 'array',
4113
+ items: {
4114
+ $ref: '#/components/schemas/TimeSeriesPointDto'
4115
+ }
4116
+ },
4117
+ summary: {
4118
+ description: 'Period summary',
4119
+ allOf: [
4120
+ {
4121
+ $ref: '#/components/schemas/TrendSummaryDto'
4122
+ }
4123
+ ]
4124
+ },
4125
+ period: {
4126
+ type: 'string',
4127
+ description: 'Period requested',
4128
+ example: '6m'
4129
+ },
4130
+ granularity: {
4131
+ type: 'string',
4132
+ description: 'Data granularity',
4133
+ example: 'month'
4134
+ },
4135
+ currency: {
4136
+ type: 'string',
4137
+ description: 'Base currency for converted values',
4138
+ example: 'CNY'
4139
+ },
4140
+ byCurrency: {
4141
+ description:
4142
+ 'Multi-currency time series (each point has currency breakdown)',
4143
+ type: 'array',
4144
+ items: {
4145
+ $ref: '#/components/schemas/MultiCurrencyPointDto'
4146
+ }
4147
+ },
4148
+ warnings: {
4149
+ description: 'Exchange rate warnings',
4150
+ type: 'array',
4151
+ items: {
4152
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
4153
+ }
4154
+ }
4155
+ },
4156
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
4157
+ } as const;
4158
+
4159
+ export const $CashFlowPointDto = {
4160
+ type: 'object',
4161
+ properties: {
4162
+ month: {
4163
+ type: 'string',
4164
+ description: 'Month key (YYYY-MM)',
4165
+ example: '2024-03'
4166
+ },
4167
+ income: {
4168
+ type: 'string',
4169
+ description: 'Income in base currency (absolute, converted)',
4170
+ example: '10000.00'
4171
+ },
4172
+ expense: {
4173
+ type: 'string',
4174
+ description: 'Expense in base currency (absolute, converted)',
4175
+ example: '5000.00'
4176
+ },
4177
+ netSavings: {
4178
+ type: 'string',
4179
+ description: 'netSavings = income − expense (savings positive)',
4180
+ example: '5000.00'
4181
+ }
4182
+ },
4183
+ required: ['month', 'income', 'expense', 'netSavings']
4184
+ } as const;
4185
+
4186
+ export const $CashFlowTrendSummaryDto = {
4187
+ type: 'object',
4188
+ properties: {
4189
+ totalIncome: {
4190
+ type: 'string',
4191
+ description: 'Total income across the period',
4192
+ example: '60000.00'
4193
+ },
4194
+ totalExpense: {
4195
+ type: 'string',
4196
+ description: 'Total expense across the period',
4197
+ example: '30000.00'
4198
+ },
4199
+ totalNetSavings: {
4200
+ type: 'string',
4201
+ description: 'income − expense across the period',
4202
+ example: '30000.00'
4203
+ },
4204
+ averageMonthlyNetSavings: {
4205
+ type: 'string',
4206
+ description:
4207
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
4208
+ example: '5000.00'
4209
+ }
4210
+ },
4211
+ required: [
4212
+ 'totalIncome',
4213
+ 'totalExpense',
4214
+ 'totalNetSavings',
4215
+ 'averageMonthlyNetSavings'
4216
+ ]
4217
+ } as const;
4218
+
4219
+ export const $CashFlowTrendsResponseDto = {
4220
+ type: 'object',
4221
+ properties: {
4222
+ series: {
4223
+ description:
4224
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
4225
+ type: 'array',
4226
+ items: {
4227
+ $ref: '#/components/schemas/CashFlowPointDto'
4228
+ }
4229
+ },
4230
+ summary: {
4231
+ description: 'Period totals',
4232
+ allOf: [
4233
+ {
4234
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
4235
+ }
4236
+ ]
4237
+ },
4238
+ period: {
4239
+ type: 'string',
4240
+ description: 'Period requested',
4241
+ example: '6m'
4242
+ },
4243
+ granularity: {
4244
+ type: 'string',
4245
+ description: 'Data granularity (v1 returns month buckets)',
4246
+ example: 'month'
4247
+ },
4248
+ currency: {
4249
+ type: 'string',
4250
+ description: 'Base currency for converted values',
4251
+ example: 'CNY'
4252
+ },
4253
+ warnings: {
4254
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
4255
+ type: 'array',
4256
+ items: {
4257
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
4258
+ }
4259
+ }
4260
+ },
4261
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
4262
+ } as const;
4263
+
4264
+ export const $GenerateSnapshotBody = {
4265
+ type: 'object',
4266
+ properties: {}
4267
+ } as const;
4268
+
4269
+ export const $GenerateSnapshotResponse = {
4270
+ type: 'object',
4271
+ properties: {}
4272
+ } as const;
4273
+
4274
+ export const $BackfillSnapshotsBody = {
4275
+ type: 'object',
4276
+ properties: {}
4277
+ } as const;
4278
+
4279
+ export const $BackfillSnapshotsResponse = {
4280
+ type: 'object',
4281
+ properties: {}
4282
+ } as const;
4283
+
4284
+ export const $DeleteOwnUserDto = {
4285
+ type: 'object',
4286
+ properties: {
4287
+ accessToken: {
4288
+ type: 'string',
4289
+ description: 'Access token for user verification',
4290
+ example: 'abc123xyz'
4291
+ }
4292
+ },
4293
+ required: ['accessToken']
4294
+ } as const;
4295
+
4296
+ export const $UserSettingsResponseDto = {
4297
+ type: 'object',
4298
+ properties: {
4299
+ baseCurrency: {
4300
+ type: 'string',
4301
+ description:
4302
+ 'Base currency (ISO 4217) for net-worth/report aggregation. Independent of region (ADR-0006).',
4303
+ example: 'USD',
4304
+ nullable: true
4305
+ }
4306
+ },
4307
+ required: ['baseCurrency']
4308
+ } as const;
4309
+
4310
+ export const $UserResponseDto = {
4311
+ type: 'object',
4312
+ properties: {
4313
+ id: {
4314
+ type: 'string',
4315
+ description: 'User ID'
4316
+ },
4317
+ role: {
4318
+ type: 'string',
4319
+ description: 'Assigned user role'
4320
+ },
4321
+ permissions: {
4322
+ description: 'Permission strings',
4323
+ type: 'array',
4324
+ items: {
4325
+ type: 'string'
4326
+ }
4327
+ },
4328
+ settings: {
4329
+ description: 'User settings',
4330
+ allOf: [
4331
+ {
4332
+ $ref: '#/components/schemas/UserSettingsResponseDto'
4333
+ }
4334
+ ]
4335
+ }
4336
+ },
4337
+ required: ['id', 'role', 'permissions', 'settings']
4338
+ } as const;
4339
+
4340
+ export const $SignupDto = {
4341
+ type: 'object',
4342
+ properties: {
4343
+ turnstileToken: {
4344
+ type: 'string',
4345
+ description:
4346
+ 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4347
+ example: '0.abc123def456...'
4348
+ }
4349
+ }
4350
+ } as const;
4351
+
4352
+ export const $SignupResponseDto = {
4353
+ type: 'object',
4354
+ properties: {
4355
+ authToken: {
4356
+ type: 'string',
4357
+ description: 'JWT auth token',
4358
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
4359
+ },
4360
+ accessToken: {
4361
+ type: 'string',
4362
+ description: 'Auto-generated access token'
4363
+ },
4364
+ role: {
4365
+ type: 'string',
4366
+ description: 'Assigned user role',
4367
+ enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
4368
+ }
4369
+ },
4370
+ required: ['authToken', 'accessToken', 'role']
4371
+ } as const;
4372
+
4373
+ export const $UpdateUserSettingDto = {
4374
+ type: 'object',
4375
+ properties: {
4376
+ secId: {
4377
+ type: 'number',
4378
+ description: 'Security ID'
4379
+ },
4380
+ annualInterestRate: {
4381
+ type: 'number',
4382
+ description: 'Annual interest rate',
4383
+ example: 0.05
4384
+ },
4385
+ currency: {
4386
+ type: 'string',
4387
+ description: 'Currency code',
4388
+ example: 'USD'
4389
+ },
4390
+ baseCurrency: {
4391
+ type: 'string',
4392
+ description: 'Base currency code',
4393
+ example: 'USD'
4394
+ },
4395
+ benchmark: {
4396
+ type: 'string',
4397
+ description: 'Benchmark symbol',
4398
+ example: 'SPY'
4399
+ },
4400
+ colorScheme: {
4401
+ type: 'string',
4402
+ description: 'Color scheme',
4403
+ enum: ['DARK', 'LIGHT']
4404
+ },
4405
+ dateRange: {
4406
+ type: 'string',
4407
+ description: 'Date range filter',
4408
+ example: '1y'
4409
+ },
4410
+ emergencyFund: {
4411
+ type: 'number',
4412
+ description: 'Emergency fund amount',
4413
+ example: 10000
4414
+ },
4415
+ 'filters.accounts': {
4416
+ description: 'Account filter IDs',
4417
+ type: 'array',
4418
+ items: {
4419
+ type: 'string'
4420
+ }
4421
+ },
4422
+ 'filters.assetClasses': {
4423
+ description: 'Asset class filters',
4424
+ type: 'array',
4425
+ items: {
4426
+ type: 'string'
4427
+ }
4428
+ },
4429
+ 'filters.dataSource': {
4430
+ type: 'string',
4431
+ description: 'Data source filter'
4432
+ },
4433
+ 'filters.symbol': {
4434
+ type: 'string',
4435
+ description: 'Symbol filter'
4436
+ },
4437
+ 'filters.tags': {
4438
+ description: 'Tag filters',
4439
+ type: 'array',
4440
+ items: {
4441
+ type: 'string'
4442
+ }
4443
+ },
4444
+ isExperimentalFeatures: {
4445
+ type: 'boolean',
4446
+ description: 'Enable experimental features'
4447
+ },
4448
+ isRestrictedView: {
4449
+ type: 'boolean',
4450
+ description: 'Enable restricted view mode'
4451
+ },
4452
+ language: {
4453
+ type: 'string',
4454
+ description: 'Language code',
4455
+ example: 'en'
4456
+ },
4457
+ locale: {
4458
+ type: 'string',
4459
+ description: 'Locale code',
4460
+ example: 'en-US'
4461
+ },
4462
+ projectedTotalAmount: {
4463
+ type: 'number',
4464
+ description: 'Projected total amount',
4465
+ example: 1000000
4466
+ },
4467
+ retirementDate: {
4468
+ type: 'string',
4469
+ description: 'Retirement date in ISO 8601 format',
4470
+ example: '2050-01-01'
4471
+ },
4472
+ savingsRate: {
4473
+ type: 'number',
4474
+ description: 'Savings rate percentage',
4475
+ example: 0.2
4476
+ },
4477
+ viewMode: {
4478
+ type: 'string',
4479
+ description: 'View mode',
4480
+ enum: ['DEFAULT', 'ZEN']
4481
+ }
4482
+ }
4483
+ } as const;
4484
+
4485
+ export const $UpdatePropertyDto = {
4486
+ type: 'object',
4487
+ properties: {
4488
+ value: {
4489
+ type: 'string',
4490
+ description: 'Property value'
4491
+ }
4492
+ },
4493
+ required: ['value']
4494
+ } as const;
4495
+
4496
+ export const $CreateTransactionRuleDto = {
4497
+ type: 'object',
4498
+ properties: {
4499
+ name: {
4500
+ type: 'string',
4501
+ minLength: 1,
4502
+ maxLength: 100
4503
+ },
4504
+ description: {
4505
+ type: 'string',
4506
+ maxLength: 500
4507
+ },
4508
+ narrationKeywords: {
4509
+ items: {
4510
+ type: 'array'
4511
+ },
4512
+ maxItems: 50,
4513
+ type: 'array'
3736
4514
  },
3737
4515
  payeeKeywords: {
3738
4516
  items: {
@@ -4364,151 +5142,67 @@ export const $TestRuleResponseDto = {
4364
5142
  required: ['ruleId', 'matches', 'confidence', 'matchDetails']
4365
5143
  } as const;
4366
5144
 
4367
- export const $DeleteOwnUserDto = {
4368
- type: 'object',
4369
- properties: {
4370
- accessToken: {
4371
- type: 'string',
4372
- description: 'Access token for user verification',
4373
- example: 'abc123xyz'
4374
- }
4375
- },
4376
- required: ['accessToken']
4377
- } as const;
4378
-
4379
- export const $SignupDto = {
4380
- type: 'object',
4381
- properties: {
4382
- turnstileToken: {
4383
- type: 'string',
4384
- description:
4385
- 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4386
- example: '0.abc123def456...'
4387
- }
4388
- }
4389
- } as const;
4390
-
4391
- export const $UpdateUserSettingDto = {
5145
+ export const $CategoryCatalogEntryDto = {
4392
5146
  type: 'object',
4393
5147
  properties: {
4394
- secId: {
4395
- type: 'number',
4396
- description: 'Security ID'
4397
- },
4398
- annualInterestRate: {
4399
- type: 'number',
4400
- description: 'Annual interest rate',
4401
- example: 0.05
4402
- },
4403
- currency: {
4404
- type: 'string',
4405
- description: 'Currency code',
4406
- example: 'USD'
4407
- },
4408
- baseCurrency: {
4409
- type: 'string',
4410
- description: 'Base currency code',
4411
- example: 'USD'
4412
- },
4413
- benchmark: {
5148
+ slug: {
4414
5149
  type: 'string',
4415
- description: 'Benchmark symbol',
4416
- example: 'SPY'
5150
+ description: 'Category slug (single source-of-truth)',
5151
+ example: 'food'
4417
5152
  },
4418
- colorScheme: {
5153
+ scenario: {
4419
5154
  type: 'string',
4420
- description: 'Color scheme',
4421
- enum: ['DARK', 'LIGHT']
5155
+ description: 'Display scenario group (maps to frontend picker _scenario)',
5156
+ enum: [
5157
+ 'expense',
5158
+ 'income',
5159
+ 'investment',
5160
+ 'banking',
5161
+ 'transfer',
5162
+ 'payment'
5163
+ ],
5164
+ example: 'expense'
4422
5165
  },
4423
- dateRange: {
5166
+ icon: {
4424
5167
  type: 'string',
4425
- description: 'Date range filter',
4426
- example: '1y'
4427
- },
4428
- emergencyFund: {
4429
- type: 'number',
4430
- description: 'Emergency fund amount',
4431
- example: 10000
4432
- },
4433
- 'filters.accounts': {
4434
- description: 'Account filter IDs',
4435
- type: 'array',
4436
- items: {
4437
- type: 'string'
4438
- }
5168
+ description: 'Lucide icon name',
5169
+ example: 'utensils'
4439
5170
  },
4440
- 'filters.assetClasses': {
4441
- description: 'Asset class filters',
5171
+ regions: {
5172
+ description: "Applicable regions ('*' = all, 'cn' = CN-only)",
5173
+ example: ['*'],
4442
5174
  type: 'array',
4443
5175
  items: {
4444
5176
  type: 'string'
4445
5177
  }
4446
- },
4447
- 'filters.dataSource': {
4448
- type: 'string',
4449
- description: 'Data source filter'
4450
- },
4451
- 'filters.symbol': {
4452
- type: 'string',
4453
- description: 'Symbol filter'
4454
- },
4455
- 'filters.tags': {
4456
- description: 'Tag filters',
5178
+ }
5179
+ },
5180
+ required: ['slug', 'scenario', 'icon', 'regions']
5181
+ } as const;
5182
+
5183
+ export const $CategoryCatalogListResponseDto = {
5184
+ type: 'object',
5185
+ properties: {
5186
+ items: {
5187
+ description: 'Category entries (region-scoped, query-filtered)',
4457
5188
  type: 'array',
4458
5189
  items: {
4459
- type: 'string'
5190
+ $ref: '#/components/schemas/CategoryCatalogEntryDto'
4460
5191
  }
4461
5192
  },
4462
- isExperimentalFeatures: {
4463
- type: 'boolean',
4464
- description: 'Enable experimental features'
4465
- },
4466
- isRestrictedView: {
4467
- type: 'boolean',
4468
- description: 'Enable restricted view mode'
4469
- },
4470
- language: {
4471
- type: 'string',
4472
- description: 'Language code',
4473
- example: 'en'
4474
- },
4475
- locale: {
4476
- type: 'string',
4477
- description: 'Locale code',
4478
- example: 'en-US'
4479
- },
4480
- projectedTotalAmount: {
4481
- type: 'number',
4482
- description: 'Projected total amount',
4483
- example: 1000000
4484
- },
4485
- retirementDate: {
4486
- type: 'string',
4487
- description: 'Retirement date in ISO 8601 format',
4488
- example: '2050-01-01'
4489
- },
4490
- savingsRate: {
5193
+ total: {
4491
5194
  type: 'number',
4492
- description: 'Savings rate percentage',
4493
- example: 0.2
5195
+ description:
5196
+ 'Total category entries for the region (before query filtering)',
5197
+ example: 30
4494
5198
  },
4495
- viewMode: {
4496
- type: 'string',
4497
- description: 'View mode',
4498
- enum: ['DEFAULT', 'ZEN']
4499
- }
4500
- }
4501
- } as const;
4502
-
4503
- export const $UpdatePropertyDto = {
4504
- type: 'object',
4505
- properties: {
4506
- value: {
5199
+ region: {
4507
5200
  type: 'string',
4508
- description: 'Property value'
5201
+ description: 'Region code',
5202
+ example: 'cn'
4509
5203
  }
4510
5204
  },
4511
- required: ['value']
5205
+ required: ['items', 'total', 'region']
4512
5206
  } as const;
4513
5207
 
4514
5208
  export const $CreateBeanEventDto = {
@@ -5253,7 +5947,8 @@ export const $UpdateMapperDefaultsDto = {
5253
5947
  type: 'string',
5254
5948
  description: 'Source account for transactions (Beancount format)',
5255
5949
  example: 'Assets:CN:Alipay:Balance',
5256
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
5950
+ pattern:
5951
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5257
5952
  },
5258
5953
  currency: {
5259
5954
  type: 'string',
@@ -5267,13 +5962,15 @@ export const $UpdateMapperDefaultsDto = {
5267
5962
  type: 'string',
5268
5963
  description: 'Default expense account (optional)',
5269
5964
  example: 'Expenses:Unknown',
5270
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
5965
+ pattern:
5966
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5271
5967
  },
5272
5968
  incomeAccount: {
5273
5969
  type: 'string',
5274
5970
  description: 'Default income account (optional)',
5275
5971
  example: 'Income:Unknown',
5276
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
5972
+ pattern:
5973
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5277
5974
  },
5278
5975
  methodAccountMapping: {
5279
5976
  type: 'object',
@@ -5330,12 +6027,14 @@ export const $ProviderSyncConfigDto = {
5330
6027
  },
5331
6028
  defaultExpenseAccount: {
5332
6029
  type: 'string',
5333
- description: 'Default expense account for the second posting',
6030
+ description:
6031
+ 'Default expense account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5334
6032
  example: 'Expenses:Unknown'
5335
6033
  },
5336
6034
  defaultIncomeAccount: {
5337
6035
  type: 'string',
5338
- description: 'Default income account for the second posting',
6036
+ description:
6037
+ 'Default income account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5339
6038
  example: 'Income:Unknown'
5340
6039
  },
5341
6040
  filterPending: {
@@ -5350,12 +6049,7 @@ export const $ProviderSyncConfigDto = {
5350
6049
  example: 'acc_gocardless_001'
5351
6050
  }
5352
6051
  },
5353
- required: [
5354
- 'sourceAccount',
5355
- 'defaultCurrency',
5356
- 'defaultExpenseAccount',
5357
- 'defaultIncomeAccount'
5358
- ]
6052
+ required: ['sourceAccount', 'defaultCurrency']
5359
6053
  } as const;
5360
6054
 
5361
6055
  export const $ProviderSyncDto = {
@@ -5565,15 +6259,105 @@ export const $UncoveredFormatMissDto = {
5565
6259
  properties: {}
5566
6260
  } as const;
5567
6261
 
6262
+ export const $ClientParsedDataDto = {
6263
+ type: 'object',
6264
+ properties: {
6265
+ amount: {
6266
+ type: 'number',
6267
+ description: 'Transaction amount',
6268
+ example: 35
6269
+ },
6270
+ currency: {
6271
+ type: 'string',
6272
+ description: 'Currency code',
6273
+ example: 'CNY'
6274
+ },
6275
+ date: {
6276
+ type: 'string',
6277
+ description: 'Transaction date (ISO 8601)',
6278
+ example: '2026-08-15'
6279
+ },
6280
+ payee: {
6281
+ type: 'string',
6282
+ description: 'Payee/merchant name',
6283
+ example: 'Starbucks'
6284
+ },
6285
+ narration: {
6286
+ type: 'string',
6287
+ description: 'Transaction narration'
6288
+ },
6289
+ category: {
6290
+ type: 'string',
6291
+ description: 'Category slug',
6292
+ example: 'food_restaurant'
6293
+ },
6294
+ incomeType: {
6295
+ type: 'string',
6296
+ description: 'Income type',
6297
+ example: 'Salary'
6298
+ },
6299
+ incomeSource: {
6300
+ type: 'string',
6301
+ description: 'Income source',
6302
+ example: 'Anthropic Inc.'
6303
+ },
6304
+ symbol: {
6305
+ type: 'string',
6306
+ description: 'Security symbol code (e.g., 600519, AAPL)',
6307
+ example: 'AAPL'
6308
+ },
6309
+ quantity: {
6310
+ type: 'number',
6311
+ description: 'Quantity of shares/units',
6312
+ example: 100
6313
+ },
6314
+ price: {
6315
+ type: 'number',
6316
+ description: 'Unit price per share/unit',
6317
+ example: 1900
6318
+ },
6319
+ investmentAction: {
6320
+ type: 'string',
6321
+ description: 'Investment action',
6322
+ enum: ['buy', 'sell'],
6323
+ example: 'buy'
6324
+ },
6325
+ paymentSource: {
6326
+ type: 'string',
6327
+ description: 'Payment source: asset (default) or liability (credit card)',
6328
+ enum: ['asset', 'liability'],
6329
+ example: 'asset'
6330
+ },
6331
+ liabilityHint: {
6332
+ type: 'string',
6333
+ description: 'Liability account hint (CreditCard/Huabei/Baitiao)',
6334
+ example: 'CreditCard'
6335
+ },
6336
+ warning: {
6337
+ type: 'string',
6338
+ description:
6339
+ 'Display-only warning from the prior response; accepted but ignored.',
6340
+ example: 'Cross-currency settlement applies.'
6341
+ }
6342
+ }
6343
+ } as const;
6344
+
5568
6345
  export const $ProcessNlpDto = {
5569
6346
  type: 'object',
5570
6347
  properties: {
5571
6348
  message: {
5572
6349
  type: 'string',
5573
- description: 'Natural language text describing a transaction (Chinese)',
5574
- example: 'yesterday Starbucks spent 35 yuan',
6350
+ description:
6351
+ 'Natural language text describing a transaction. Optional when `confirm` is true (structured confirm); otherwise required.',
6352
+ example: 'Starbucks 35',
5575
6353
  maxLength: 500
5576
6354
  },
6355
+ confirm: {
6356
+ type: 'boolean',
6357
+ description:
6358
+ 'Structured confirm signal — bypasses NL confirm-word matching when true. Send parsedData field edits alongside. The NL word-list path is the fallback.',
6359
+ example: true
6360
+ },
5577
6361
  sessionId: {
5578
6362
  type: 'string',
5579
6363
  description:
@@ -5581,17 +6365,32 @@ export const $ProcessNlpDto = {
5581
6365
  example: 'session_abc123'
5582
6366
  },
5583
6367
  parsedData: {
5584
- type: 'object',
5585
6368
  description:
5586
6369
  'Parsed data from previous NLP response for session recovery. Send back the parsedData received in confirm_payee/confirm responses.',
5587
6370
  example: {
5588
6371
  amount: 35,
5589
6372
  currency: 'CNY',
5590
6373
  payee: 'Starbucks'
5591
- }
6374
+ },
6375
+ allOf: [
6376
+ {
6377
+ $ref: '#/components/schemas/ClientParsedDataDto'
6378
+ }
6379
+ ]
6380
+ },
6381
+ selectedRuleId: {
6382
+ type: 'string',
6383
+ description:
6384
+ 'confirm_rule echo-back: rule id selected from the prior confirm_rule response (matchedRule.id or alternatives[i].ruleId). Applied directly when the session is confirming_rule — no NL re-parse.',
6385
+ example: 'rule_abc123'
6386
+ },
6387
+ selectedAccount: {
6388
+ type: 'string',
6389
+ description:
6390
+ 'confirm_account echo-back: account path selected from the prior confirm_account response (suggestedAccount, similarAccounts[i].path, or a typed path). Applied directly when the session is confirming_account — no NL re-parse.',
6391
+ example: 'Expenses:Food:Coffee'
5592
6392
  }
5593
- },
5594
- required: ['message']
6393
+ }
5595
6394
  } as const;
5596
6395
 
5597
6396
  export const $NlpTransactionInfoDto = {
@@ -5894,13 +6693,31 @@ export const $NlpRuleConfirmationDataDto = {
5894
6693
  }
5895
6694
  }
5896
6695
  },
5897
- required: [
5898
- 'confidence',
5899
- 'matchedRule',
5900
- 'suggestedAccounts',
5901
- 'alternatives',
5902
- 'reasons'
5903
- ]
6696
+ required: [
6697
+ 'confidence',
6698
+ 'matchedRule',
6699
+ 'suggestedAccounts',
6700
+ 'alternatives',
6701
+ 'reasons'
6702
+ ]
6703
+ } as const;
6704
+
6705
+ export const $NlpAccountCandidateDto = {
6706
+ type: 'object',
6707
+ properties: {
6708
+ path: {
6709
+ type: 'string',
6710
+ description: 'Canonical beancount account path (echo back on selection)',
6711
+ example: 'Expenses:Food:Dining'
6712
+ },
6713
+ name: {
6714
+ type: 'string',
6715
+ description:
6716
+ 'Localized display name (ADR-0114 read-time projection, user locale)',
6717
+ example: '餐饮'
6718
+ }
6719
+ },
6720
+ required: ['path', 'name']
5904
6721
  } as const;
5905
6722
 
5906
6723
  export const $NlpAccountConfirmationDataDto = {
@@ -5913,14 +6730,16 @@ export const $NlpAccountConfirmationDataDto = {
5913
6730
  },
5914
6731
  suggestedAccount: {
5915
6732
  type: 'string',
5916
- description: 'Suggested replacement account',
6733
+ description:
6734
+ 'Suggested replacement account (omitted when no clear candidate)',
5917
6735
  example: 'Expenses:Food:Drinks'
5918
6736
  },
5919
6737
  similarAccounts: {
5920
- description: 'Similar accounts for user selection',
6738
+ description:
6739
+ 'Similar accounts for user selection (path + localized name, #680)',
5921
6740
  type: 'array',
5922
6741
  items: {
5923
- type: 'string'
6742
+ $ref: '#/components/schemas/NlpAccountCandidateDto'
5924
6743
  }
5925
6744
  },
5926
6745
  errorMessage: {
@@ -5935,7 +6754,6 @@ export const $NlpAccountConfirmationDataDto = {
5935
6754
  },
5936
6755
  required: [
5937
6756
  'invalidAccount',
5938
- 'suggestedAccount',
5939
6757
  'similarAccounts',
5940
6758
  'errorMessage',
5941
6759
  'transactionContext'
@@ -6108,7 +6926,8 @@ export const $NlpSuggestedAccountDto = {
6108
6926
  },
6109
6927
  confidence: {
6110
6928
  type: 'number',
6111
- description: 'Confidence score for this suggestion (0-1)',
6929
+ description:
6930
+ 'Confidence score for this suggestion (0-1). Present = predicted (confirm/confirm_rule/confirm_account); omitted = actual persisted account (created). (#586)',
6112
6931
  example: 0.9
6113
6932
  }
6114
6933
  },
@@ -6144,23 +6963,31 @@ export const $NlpDefaultAccountsDto = {
6144
6963
  properties: {
6145
6964
  asset: {
6146
6965
  type: 'string',
6147
- description: 'Default asset account',
6148
- example: 'Assets:Checking'
6966
+ description:
6967
+ 'Default OPEN asset account (MRU when multiple), or null when none/ambiguous',
6968
+ example: 'Assets:Checking',
6969
+ nullable: true
6149
6970
  },
6150
6971
  expense: {
6151
6972
  type: 'string',
6152
- description: 'Default expense account',
6153
- example: 'Expenses:Uncategorized'
6973
+ description:
6974
+ 'Default OPEN expense account (MRU when multiple), or null when none/ambiguous',
6975
+ example: 'Expenses:Food:Coffee',
6976
+ nullable: true
6154
6977
  },
6155
6978
  income: {
6156
6979
  type: 'string',
6157
- description: 'Default income account',
6158
- example: 'Income:Uncategorized'
6980
+ description:
6981
+ 'Default OPEN income account (MRU when multiple), or null when none/ambiguous',
6982
+ example: 'Income:Salary',
6983
+ nullable: true
6159
6984
  },
6160
6985
  liability: {
6161
6986
  type: 'string',
6162
- description: 'Default liability account',
6163
- example: 'Liabilities:CreditCard'
6987
+ description:
6988
+ 'Default OPEN liability account (MRU when multiple), or null when none/ambiguous',
6989
+ example: 'Liabilities:CreditCard',
6990
+ nullable: true
6164
6991
  }
6165
6992
  },
6166
6993
  required: ['asset', 'expense', 'income', 'liability']
@@ -6185,7 +7012,8 @@ export const $NlpResponseDto = {
6185
7012
  'confirm_rule',
6186
7013
  'confirm_account',
6187
7014
  'confirm_payee',
6188
- 'cancel'
7015
+ 'cancel',
7016
+ 'aborted'
6189
7017
  ]
6190
7018
  },
6191
7019
  intent: {
@@ -6199,7 +7027,7 @@ export const $NlpResponseDto = {
6199
7027
  type: 'string',
6200
7028
  description:
6201
7029
  'Asset sub-type (only present when intent is "asset"). Determines which asset-related form to render.',
6202
- enum: ['transfer', 'banking', 'investment'],
7030
+ enum: ['transfer', 'banking', 'investment', 'lend', 'lend_collect'],
6203
7031
  example: 'investment'
6204
7032
  },
6205
7033
  liabilitySubType: {
@@ -6347,7 +7175,7 @@ export const $NlpResponseDto = {
6347
7175
  },
6348
7176
  suggestedAccounts: {
6349
7177
  description:
6350
- 'Suggested accounts for this transaction. Contains recommended source and destination accounts based on the detected intent and rules.',
7178
+ 'Suggested accounts for this transaction (#586). confirm/confirm_rule/confirm_account: predicted (source/destination carry confidence); created: actual persisted accounts (confidence omitted). confirm_account destination is the suggested replacement, never the invalid account.',
6351
7179
  allOf: [
6352
7180
  {
6353
7181
  $ref: '#/components/schemas/NlpSuggestedAccountsDto'
@@ -6356,7 +7184,7 @@ export const $NlpResponseDto = {
6356
7184
  },
6357
7185
  defaultAccounts: {
6358
7186
  description:
6359
- 'Default accounts for the user/region. These are fallback accounts used when no specific suggestion is available.',
7187
+ 'Default fallback accounts for the user/region (#586). v1 returns universal constants; per-user personalization is planned.',
6360
7188
  allOf: [
6361
7189
  {
6362
7190
  $ref: '#/components/schemas/NlpDefaultAccountsDto'
@@ -6367,6 +7195,178 @@ export const $NlpResponseDto = {
6367
7195
  required: ['status', 'action']
6368
7196
  } as const;
6369
7197
 
7198
+ export const $PlatformListItemDto = {
7199
+ type: 'object',
7200
+ properties: {
7201
+ id: {
7202
+ type: 'string',
7203
+ description: 'Global platform ID'
7204
+ },
7205
+ name: {
7206
+ type: 'string',
7207
+ description: 'Platform name'
7208
+ },
7209
+ url: {
7210
+ type: 'string',
7211
+ description: 'Platform URL'
7212
+ },
7213
+ type: {
7214
+ type: 'string',
7215
+ description: 'Platform type',
7216
+ enum: [
7217
+ 'BANK',
7218
+ 'BROKERAGE',
7219
+ 'CRYPTO_EXCHANGE',
7220
+ 'PAYMENT',
7221
+ 'INVESTMENT',
7222
+ 'INSURANCE',
7223
+ 'OTHER'
7224
+ ]
7225
+ },
7226
+ canonical: {
7227
+ type: 'string',
7228
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7229
+ },
7230
+ suggestedSegment: {
7231
+ type: 'string',
7232
+ description:
7233
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7234
+ },
7235
+ logoUrl: {
7236
+ type: 'string',
7237
+ description: 'Logo URL',
7238
+ nullable: true
7239
+ },
7240
+ countryCode: {
7241
+ type: 'string',
7242
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7243
+ example: 'CN',
7244
+ nullable: true
7245
+ },
7246
+ category: {
7247
+ type: 'string',
7248
+ description:
7249
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7250
+ nullable: true,
7251
+ example: 'DigitalWallet'
7252
+ },
7253
+ isBound: {
7254
+ type: 'boolean',
7255
+ description: 'Whether user has accounts using this platform'
7256
+ }
7257
+ },
7258
+ required: [
7259
+ 'id',
7260
+ 'name',
7261
+ 'url',
7262
+ 'type',
7263
+ 'canonical',
7264
+ 'suggestedSegment',
7265
+ 'logoUrl',
7266
+ 'countryCode',
7267
+ 'category',
7268
+ 'isBound'
7269
+ ]
7270
+ } as const;
7271
+
7272
+ export const $PlatformMatchResultDto = {
7273
+ type: 'object',
7274
+ properties: {
7275
+ id: {
7276
+ type: 'string',
7277
+ description: 'Global platform ID'
7278
+ },
7279
+ name: {
7280
+ type: 'string',
7281
+ description: 'Platform name (e.g., "ICBC")'
7282
+ },
7283
+ canonical: {
7284
+ type: 'string',
7285
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7286
+ },
7287
+ type: {
7288
+ type: 'string',
7289
+ description: 'Platform type',
7290
+ enum: [
7291
+ 'BANK',
7292
+ 'BROKERAGE',
7293
+ 'CRYPTO_EXCHANGE',
7294
+ 'PAYMENT',
7295
+ 'INVESTMENT',
7296
+ 'INSURANCE',
7297
+ 'OTHER'
7298
+ ]
7299
+ },
7300
+ suggestedSegment: {
7301
+ type: 'string',
7302
+ description:
7303
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7304
+ },
7305
+ logoUrl: {
7306
+ type: 'string',
7307
+ description: 'Logo URL',
7308
+ nullable: true
7309
+ },
7310
+ countryCode: {
7311
+ type: 'string',
7312
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7313
+ example: 'CN',
7314
+ nullable: true
7315
+ },
7316
+ category: {
7317
+ type: 'string',
7318
+ description:
7319
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7320
+ nullable: true,
7321
+ example: 'DigitalWallet'
7322
+ },
7323
+ matchType: {
7324
+ type: 'string',
7325
+ description: "How this row matched: 'exact' > 'prefix' > 'substring'",
7326
+ enum: ['exact', 'prefix', 'substring']
7327
+ }
7328
+ },
7329
+ required: [
7330
+ 'id',
7331
+ 'name',
7332
+ 'canonical',
7333
+ 'type',
7334
+ 'suggestedSegment',
7335
+ 'logoUrl',
7336
+ 'countryCode',
7337
+ 'category',
7338
+ 'matchType'
7339
+ ]
7340
+ } as const;
7341
+
7342
+ export const $PlatformMatchResponseDto = {
7343
+ type: 'object',
7344
+ properties: {
7345
+ platforms: {
7346
+ description: 'Ranked matches, best tier first (at most 10 rows)',
7347
+ type: 'array',
7348
+ items: {
7349
+ $ref: '#/components/schemas/PlatformMatchResultDto'
7350
+ }
7351
+ },
7352
+ matchType: {
7353
+ type: 'string',
7354
+ description:
7355
+ "Overall match quality — top row's tier, or 'none' when no hits",
7356
+ enum: ['none', 'exact', 'prefix', 'substring']
7357
+ },
7358
+ total: {
7359
+ type: 'number',
7360
+ description: 'Total matches before LIMIT (truncation transparency)'
7361
+ },
7362
+ hasMore: {
7363
+ type: 'boolean',
7364
+ description: 'true when total > platforms.length (more matches exist)'
7365
+ }
7366
+ },
7367
+ required: ['platforms', 'matchType', 'total', 'hasMore']
7368
+ } as const;
7369
+
6370
7370
  export const $CreatePlatformDto = {
6371
7371
  type: 'object',
6372
7372
  properties: {
@@ -7561,292 +8561,378 @@ export const $HoldingPnlResponseDto = {
7561
8561
  required: ['asOfDate', 'baseCurrency', 'method', 'rows', 'warnings']
7562
8562
  } as const;
7563
8563
 
7564
- export const $CurrencyBalanceDto = {
7565
- type: 'object',
7566
- properties: {
7567
- currency: {
7568
- type: 'string',
7569
- description: 'ISO 4217 currency code',
7570
- example: 'CNY'
7571
- },
7572
- balance: {
7573
- type: 'string',
7574
- description: 'Balance amount',
7575
- example: '500000.00'
7576
- }
7577
- },
7578
- required: ['currency', 'balance']
7579
- } as const;
7580
-
7581
- export const $TimeSeriesPointDto = {
7582
- type: 'object',
7583
- properties: {
7584
- date: {
7585
- type: 'string',
7586
- description: 'Date in YYYY-MM-DD format',
7587
- example: '2024-06-15'
7588
- },
7589
- value: {
7590
- type: 'string',
7591
- description: 'Value at this date (in base currency)',
7592
- example: '500000.00'
7593
- },
7594
- change: {
7595
- type: 'object',
7596
- description: 'Change from previous point',
7597
- example: '5000.00'
7598
- },
7599
- assets: {
7600
- type: 'string',
7601
- description: 'Total assets at this date (in base currency)',
7602
- example: '494338.00'
7603
- },
7604
- liabilities: {
7605
- type: 'string',
7606
- description: 'Total liabilities at this date (in base currency)',
7607
- example: '310098.00'
7608
- },
7609
- byCurrency: {
7610
- description: 'Multi-currency breakdown for this point',
7611
- type: 'array',
7612
- items: {
7613
- $ref: '#/components/schemas/CurrencyBalanceDto'
7614
- }
7615
- }
7616
- },
7617
- required: ['date', 'value']
7618
- } as const;
7619
-
7620
- export const $TrendSummaryDto = {
8564
+ export const $AnonymousLoginDto = {
7621
8565
  type: 'object',
7622
8566
  properties: {
7623
- startValue: {
7624
- type: 'string',
7625
- description: 'Value at start of period',
7626
- example: '450000.00'
7627
- },
7628
- endValue: {
7629
- type: 'string',
7630
- description: 'Value at end of period',
7631
- example: '500000.00'
7632
- },
7633
- totalChange: {
7634
- type: 'string',
7635
- description: 'Total change over period',
7636
- example: '50000.00'
7637
- },
7638
- totalChangePercentage: {
8567
+ accessToken: {
7639
8568
  type: 'string',
7640
- description: 'Total change percentage',
7641
- example: '+11.11%'
8569
+ description: 'Access token for anonymous login'
7642
8570
  }
7643
8571
  },
7644
- required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
8572
+ required: ['accessToken']
7645
8573
  } as const;
7646
8574
 
7647
- export const $MultiCurrencyPointDto = {
8575
+ export const $AnonymousLoginResponseDto = {
7648
8576
  type: 'object',
7649
8577
  properties: {
7650
- date: {
8578
+ authToken: {
7651
8579
  type: 'string',
7652
- description: 'Date in YYYY-MM-DD format',
7653
- example: '2024-06-15'
7654
- },
7655
- byCurrency: {
7656
- description: 'Balances by currency',
7657
- type: 'array',
7658
- items: {
7659
- $ref: '#/components/schemas/CurrencyBalanceDto'
7660
- }
8580
+ description: 'JWT auth token',
8581
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
7661
8582
  }
7662
8583
  },
7663
- required: ['date', 'byCurrency']
8584
+ required: ['authToken']
7664
8585
  } as const;
7665
8586
 
7666
- export const $PortfolioTrendsResponseDto = {
8587
+ export const $ParserContributionMetaDto = {
7667
8588
  type: 'object',
7668
8589
  properties: {
7669
- series: {
7670
- description: 'Time series data points',
7671
- type: 'array',
7672
- items: {
7673
- $ref: '#/components/schemas/TimeSeriesPointDto'
7674
- }
7675
- },
7676
- summary: {
7677
- description: 'Period summary',
7678
- allOf: [
7679
- {
7680
- $ref: '#/components/schemas/TrendSummaryDto'
7681
- }
8590
+ institution: {
8591
+ type: 'string',
8592
+ description: 'Institution slug (lowercase kebab-case)',
8593
+ pattern: '^[a-z0-9]+(-[a-z0-9]+)*$',
8594
+ example: 'icbc'
8595
+ },
8596
+ region: {
8597
+ type: 'string',
8598
+ enum: [
8599
+ 'cn',
8600
+ 'us',
8601
+ 'de',
8602
+ 'fr',
8603
+ 'gb',
8604
+ 'hk',
8605
+ 'jp',
8606
+ 'sg',
8607
+ 'au',
8608
+ 'ca',
8609
+ 'other'
7682
8610
  ]
7683
8611
  },
7684
- period: {
8612
+ accountType: {
7685
8613
  type: 'string',
7686
- description: 'Period requested',
7687
- example: '6m'
8614
+ enum: ['checking', 'savings', 'credit', 'debit', 'investment']
7688
8615
  },
7689
- granularity: {
8616
+ format: {
7690
8617
  type: 'string',
7691
- description: 'Data granularity',
7692
- example: 'month'
8618
+ enum: ['csv', 'xlsx', 'pdf', 'ofx', 'qif']
7693
8619
  },
7694
- currency: {
8620
+ institutionDisplayName: {
7695
8621
  type: 'string',
7696
- description: 'Base currency for converted values',
7697
- example: 'CNY'
8622
+ example: '中国工商银行'
7698
8623
  },
7699
- byCurrency: {
8624
+ encoding: {
8625
+ type: 'string',
8626
+ example: 'utf-8'
8627
+ },
8628
+ delimiter: {
8629
+ type: 'string',
8630
+ description: 'CSV delimiter character: ",", ";", "\\t" or "|"'
8631
+ },
8632
+ headerRows: {
8633
+ type: 'number',
8634
+ default: 1,
8635
+ description: 'Header row count; the client omits the field when it is 1'
8636
+ },
8637
+ notes: {
8638
+ type: 'string',
8639
+ maxLength: 2000
8640
+ }
8641
+ },
8642
+ required: ['institution', 'region', 'accountType', 'format']
8643
+ } as const;
8644
+
8645
+ export const $ParserContributionSamplesDto = {
8646
+ type: 'object',
8647
+ properties: {
8648
+ rows: {
7700
8649
  description:
7701
- 'Multi-currency time series (each point has currency breakdown)',
8650
+ 'Client-sanitized sample rows (key = column name, value = cell)',
7702
8651
  type: 'array',
7703
8652
  items: {
7704
- $ref: '#/components/schemas/MultiCurrencyPointDto'
8653
+ type: 'object'
7705
8654
  }
7706
8655
  },
7707
- warnings: {
7708
- description: 'Exchange rate warnings',
8656
+ rawHeaders: {
7709
8657
  type: 'array',
7710
8658
  items: {
7711
- $ref: '#/components/schemas/ExchangeRateWarningDto'
8659
+ type: 'string'
7712
8660
  }
7713
8661
  }
7714
8662
  },
7715
- required: ['series', 'summary', 'period', 'granularity', 'currency']
8663
+ required: ['rows']
7716
8664
  } as const;
7717
8665
 
7718
- export const $CashFlowPointDto = {
8666
+ export const $FieldHintDto = {
7719
8667
  type: 'object',
7720
8668
  properties: {
7721
- month: {
8669
+ columnName: {
7722
8670
  type: 'string',
7723
- description: 'Month key (YYYY-MM)',
7724
- example: '2024-03'
8671
+ example: '交易日期'
7725
8672
  },
7726
- income: {
8673
+ format: {
7727
8674
  type: 'string',
7728
- description: 'Income in base currency (absolute, converted)',
7729
- example: '10000.00'
8675
+ description: 'Date format, e.g. yyyy-MM-dd HH:mm',
8676
+ example: 'yyyy-MM-dd'
7730
8677
  },
7731
- expense: {
8678
+ signConvention: {
7732
8679
  type: 'string',
7733
- description: 'Expense in base currency (absolute, converted)',
7734
- example: '5000.00'
8680
+ enum: ['negative-expense', 'positive-expense', 'separate-columns']
7735
8681
  },
7736
- netSavings: {
7737
- type: 'string',
7738
- description: 'netSavings = income − expense (savings positive)',
7739
- example: '5000.00'
8682
+ creditColumn: {
8683
+ type: 'string'
8684
+ },
8685
+ debitColumn: {
8686
+ type: 'string'
7740
8687
  }
7741
8688
  },
7742
- required: ['month', 'income', 'expense', 'netSavings']
8689
+ required: ['columnName']
7743
8690
  } as const;
7744
8691
 
7745
- export const $CashFlowTrendSummaryDto = {
8692
+ export const $ParserContributionFieldHintsDto = {
7746
8693
  type: 'object',
7747
8694
  properties: {
7748
- totalIncome: {
7749
- type: 'string',
7750
- description: 'Total income across the period',
7751
- example: '60000.00'
8695
+ date: {
8696
+ $ref: '#/components/schemas/FieldHintDto'
7752
8697
  },
7753
- totalExpense: {
7754
- type: 'string',
7755
- description: 'Total expense across the period',
7756
- example: '30000.00'
8698
+ amount: {
8699
+ $ref: '#/components/schemas/FieldHintDto'
7757
8700
  },
7758
- totalNetSavings: {
7759
- type: 'string',
7760
- description: 'income − expense across the period',
7761
- example: '30000.00'
8701
+ description: {
8702
+ $ref: '#/components/schemas/FieldHintDto'
7762
8703
  },
7763
- averageMonthlyNetSavings: {
7764
- type: 'string',
7765
- description:
7766
- 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
7767
- example: '5000.00'
8704
+ balance: {
8705
+ $ref: '#/components/schemas/FieldHintDto'
8706
+ },
8707
+ payee: {
8708
+ $ref: '#/components/schemas/FieldHintDto'
8709
+ },
8710
+ reference: {
8711
+ $ref: '#/components/schemas/FieldHintDto'
8712
+ },
8713
+ category: {
8714
+ $ref: '#/components/schemas/FieldHintDto'
7768
8715
  }
7769
8716
  },
7770
- required: [
7771
- 'totalIncome',
7772
- 'totalExpense',
7773
- 'totalNetSavings',
7774
- 'averageMonthlyNetSavings'
7775
- ]
8717
+ required: ['date', 'amount']
7776
8718
  } as const;
7777
8719
 
7778
- export const $CashFlowTrendsResponseDto = {
8720
+ export const $ExpectedTransactionDto = {
7779
8721
  type: 'object',
7780
8722
  properties: {
7781
- series: {
7782
- description:
7783
- 'Monthly cash-flow series (fixed N-month window, zero-filled)',
7784
- type: 'array',
7785
- items: {
7786
- $ref: '#/components/schemas/CashFlowPointDto'
7787
- }
7788
- },
7789
- summary: {
7790
- description: 'Period totals',
7791
- allOf: [
7792
- {
7793
- $ref: '#/components/schemas/CashFlowTrendSummaryDto'
7794
- }
7795
- ]
7796
- },
7797
- period: {
8723
+ date: {
7798
8724
  type: 'string',
7799
- description: 'Period requested',
7800
- example: '6m'
8725
+ example: '2026-08-01'
7801
8726
  },
7802
- granularity: {
7803
- type: 'string',
7804
- description: 'Data granularity (v1 returns month buckets)',
7805
- example: 'month'
8727
+ amount: {
8728
+ type: 'number',
8729
+ example: -45.5
7806
8730
  },
7807
- currency: {
8731
+ description: {
7808
8732
  type: 'string',
7809
- description: 'Base currency for converted values',
7810
- example: 'CNY'
8733
+ example: '星巴克-***店'
7811
8734
  },
7812
- warnings: {
7813
- description: 'Exchange rate warnings (e.g. missing rate for a currency)',
7814
- type: 'array',
7815
- items: {
7816
- $ref: '#/components/schemas/ExchangeRateWarningDto'
7817
- }
8735
+ payee: {
8736
+ type: 'string'
8737
+ },
8738
+ category: {
8739
+ type: 'string'
7818
8740
  }
7819
8741
  },
7820
- required: ['series', 'summary', 'period', 'granularity', 'currency']
8742
+ required: ['date', 'amount', 'description']
7821
8743
  } as const;
7822
8744
 
7823
- export const $GenerateSnapshotBody = {
8745
+ export const $ParserContributionExamplesDto = {
7824
8746
  type: 'object',
7825
- properties: {}
8747
+ properties: {
8748
+ expectedTransactions: {
8749
+ type: 'array',
8750
+ items: {
8751
+ $ref: '#/components/schemas/ExpectedTransactionDto'
8752
+ }
8753
+ }
8754
+ },
8755
+ required: ['expectedTransactions']
7826
8756
  } as const;
7827
8757
 
7828
- export const $GenerateSnapshotResponse = {
8758
+ export const $ParserContributionRequestDto = {
7829
8759
  type: 'object',
7830
- properties: {}
8760
+ properties: {
8761
+ meta: {
8762
+ $ref: '#/components/schemas/ParserContributionMetaDto'
8763
+ },
8764
+ samples: {
8765
+ $ref: '#/components/schemas/ParserContributionSamplesDto'
8766
+ },
8767
+ fieldHints: {
8768
+ $ref: '#/components/schemas/ParserContributionFieldHintsDto'
8769
+ },
8770
+ examples: {
8771
+ description: 'Omitted entirely by the client when empty',
8772
+ allOf: [
8773
+ {
8774
+ $ref: '#/components/schemas/ParserContributionExamplesDto'
8775
+ }
8776
+ ]
8777
+ }
8778
+ },
8779
+ required: ['meta', 'samples', 'fieldHints']
7831
8780
  } as const;
7832
8781
 
7833
- export const $BackfillSnapshotsBody = {
8782
+ export const $ParserContributionRelayResponseDto = {
7834
8783
  type: 'object',
7835
- properties: {}
8784
+ properties: {
8785
+ issueUrl: {
8786
+ type: 'string',
8787
+ example: 'https://github.com/fire-zu/firela-vlt/issues/42'
8788
+ },
8789
+ issueNumber: {
8790
+ type: 'number',
8791
+ example: 42
8792
+ }
8793
+ },
8794
+ required: ['issueUrl', 'issueNumber']
7836
8795
  } as const;
7837
8796
 
7838
- export const $BackfillSnapshotsResponse = {
8797
+ export const $SymbolSearchResultDto = {
7839
8798
  type: 'object',
7840
- properties: {}
8799
+ properties: {
8800
+ symbol: {
8801
+ type: 'string',
8802
+ example: 'AAPL'
8803
+ },
8804
+ name: {
8805
+ type: 'object',
8806
+ example: 'Apple Inc.',
8807
+ nullable: true
8808
+ },
8809
+ exchange: {
8810
+ type: 'object',
8811
+ example: 'US',
8812
+ nullable: true
8813
+ },
8814
+ assetType: {
8815
+ type: 'object',
8816
+ description: 'OpenBB asset_type (e.g. stock, etf)',
8817
+ example: 'stock',
8818
+ nullable: true
8819
+ },
8820
+ assetClass: {
8821
+ type: 'object',
8822
+ description: 'IGN asset class (region.types.ts ASSET_CLASSES)',
8823
+ example: 'EQUITY',
8824
+ nullable: true
8825
+ },
8826
+ assetSubClass: {
8827
+ type: 'object',
8828
+ description: 'IGN asset sub-class (region.types.ts ASSET_SUB_CLASSES)',
8829
+ example: 'STOCK',
8830
+ nullable: true
8831
+ },
8832
+ currency: {
8833
+ type: 'object',
8834
+ description: 'Trading currency (extra_data or inferred from exchange)',
8835
+ example: 'USD',
8836
+ nullable: true
8837
+ }
8838
+ },
8839
+ required: ['symbol']
7841
8840
  } as const;
7842
8841
 
7843
- export const $AnonymousLoginDto = {
8842
+ export const $SymbolQuoteDto = {
7844
8843
  type: 'object',
7845
8844
  properties: {
7846
- accessToken: {
8845
+ symbol: {
7847
8846
  type: 'string',
7848
- description: 'Access token for anonymous login'
8847
+ example: 'AAPL'
8848
+ },
8849
+ name: {
8850
+ type: 'object',
8851
+ example: 'Apple Inc.',
8852
+ nullable: true
8853
+ },
8854
+ exchange: {
8855
+ type: 'object',
8856
+ example: 'US',
8857
+ nullable: true
8858
+ },
8859
+ assetType: {
8860
+ type: 'object',
8861
+ description: 'OpenBB asset_type',
8862
+ example: 'stock',
8863
+ nullable: true
8864
+ },
8865
+ assetClass: {
8866
+ type: 'object',
8867
+ description: 'IGN asset class',
8868
+ example: 'EQUITY',
8869
+ nullable: true
8870
+ },
8871
+ assetSubClass: {
8872
+ type: 'object',
8873
+ description: 'IGN asset sub-class',
8874
+ example: 'STOCK',
8875
+ nullable: true
8876
+ },
8877
+ currency: {
8878
+ type: 'object',
8879
+ description: 'Trading currency (extra_data or inferred from exchange)',
8880
+ example: 'USD',
8881
+ nullable: true
8882
+ },
8883
+ price: {
8884
+ type: 'object',
8885
+ description: 'Latest price (Decimal string)',
8886
+ example: '189.84',
8887
+ nullable: true
8888
+ },
8889
+ priceDate: {
8890
+ type: 'object',
8891
+ description: 'Date the price was observed (ISO yyyy-MM-dd)',
8892
+ example: '2026-08-05',
8893
+ nullable: true
8894
+ },
8895
+ changePercent: {
8896
+ type: 'object',
8897
+ description:
8898
+ 'Change vs previous close, in percentage points (1.7 == 1.7%). openbb stores change_percent as a normalized decimal; this exposes percentage points for frontend convenience.',
8899
+ example: 1.7,
8900
+ nullable: true
8901
+ },
8902
+ prevClose: {
8903
+ type: 'object',
8904
+ description: 'Previous close (Decimal string)',
8905
+ nullable: true
8906
+ },
8907
+ open: {
8908
+ type: 'object',
8909
+ description: 'Day open (Decimal string)',
8910
+ nullable: true
8911
+ },
8912
+ high: {
8913
+ type: 'object',
8914
+ description: 'Day high (Decimal string)',
8915
+ nullable: true
8916
+ },
8917
+ low: {
8918
+ type: 'object',
8919
+ description: 'Day low (Decimal string)',
8920
+ nullable: true
8921
+ },
8922
+ volume: {
8923
+ type: 'object',
8924
+ description: 'Day volume (Decimal string)',
8925
+ nullable: true
8926
+ },
8927
+ yearHigh: {
8928
+ type: 'object',
8929
+ description: '52-week high (Decimal string)',
8930
+ nullable: true
8931
+ },
8932
+ yearLow: {
8933
+ type: 'object',
8934
+ description: '52-week low (Decimal string)',
8935
+ nullable: true
7849
8936
  }
7850
- },
7851
- required: ['accessToken']
8937
+ }
7852
8938
  } as const;