@firela/api-types 0.0.0-canary.a90ce0e4 → 0.0.0-canary.a97b40c5

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.
@@ -51,6 +51,14 @@ export const $CreateAccountDto = {
51
51
  description: 'Icon identifier (overrides template)',
52
52
  example: 'bank-custom'
53
53
  },
54
+ displayName: {
55
+ type: 'string',
56
+ description:
57
+ 'User-set display name override (omit/null = keep the derived name)',
58
+ nullable: true,
59
+ maxLength: 50,
60
+ example: 'Salary card'
61
+ },
54
62
  openDirectiveMeta: {
55
63
  type: 'object',
56
64
  description:
@@ -88,6 +96,49 @@ export const $AccountResponseDto = {
88
96
  enum: ['Assets', 'Liabilities', 'Income', 'Expenses', 'Equity'],
89
97
  example: 'Assets'
90
98
  },
99
+ assetSubClass: {
100
+ type: 'string',
101
+ description:
102
+ '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.',
103
+ enum: [
104
+ 'DEPOSIT',
105
+ 'CASH',
106
+ 'MONEY_MARKET_FUND',
107
+ 'STOCK',
108
+ 'ETF',
109
+ 'MUTUAL_FUND',
110
+ 'EQUITY_COMPENSATION',
111
+ 'GOVERNMENT_BOND',
112
+ 'CORPORATE_BOND',
113
+ 'BOND_FUND',
114
+ 'PRIMARY_RESIDENCE',
115
+ 'INVESTMENT_PROPERTY',
116
+ 'REIT',
117
+ 'GOLD',
118
+ 'SILVER',
119
+ 'PRECIOUS_METAL',
120
+ 'PRECIOUS_METAL_FUND',
121
+ 'COMMODITY',
122
+ 'COMMODITY_FUND',
123
+ 'CRYPTOCURRENCY',
124
+ 'RETIREMENT_ACCOUNT',
125
+ 'HEALTH_ACCOUNT',
126
+ 'EDUCATION_ACCOUNT',
127
+ 'INSURANCE',
128
+ 'PRIVATE_EQUITY',
129
+ 'HEDGE_FUND',
130
+ 'COLLECTIBLES',
131
+ 'MORTGAGE',
132
+ 'STUDENT_LOAN',
133
+ 'CREDIT_CARD',
134
+ 'PERSONAL_LOAN',
135
+ 'ACCOUNTS_PAYABLE',
136
+ 'TAX_PAYABLE',
137
+ 'OTHER'
138
+ ],
139
+ nullable: true,
140
+ example: 'STOCK'
141
+ },
91
142
  status: {
92
143
  type: 'string',
93
144
  description: 'Account status',
@@ -138,7 +189,8 @@ export const $AccountResponseDto = {
138
189
  },
139
190
  displayName: {
140
191
  type: 'string',
141
- description: 'Localized display name (ADR-0114, read-time projection)',
192
+ description:
193
+ 'Display name with precedence: user-set name (#762) > ADR-0114 localized name > path leaf (read-time projection)',
142
194
  example: 'Checking'
143
195
  },
144
196
  icon: {
@@ -154,7 +206,7 @@ export const $AccountResponseDto = {
154
206
  }
155
207
  },
156
208
  platformId: {
157
- type: 'object',
209
+ type: 'string',
158
210
  description: 'Platform ID (null if unbound)',
159
211
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
160
212
  },
@@ -334,16 +386,43 @@ export const $AccountStandardResponseDto = {
334
386
  },
335
387
  name: {
336
388
  type: 'string',
337
- description: 'Short localized display name',
389
+ description:
390
+ 'Short display name. Universal rows project to the request locale (Accept-Language); regional rows keep the authored native name — mixed-language by design (ADR-0131 class P vs class A).',
338
391
  example: 'Housing Fund'
339
392
  },
393
+ aliases: {
394
+ description:
395
+ 'Authored market-language alternative names delivered verbatim (not localized copy, not xlf-managed, not locale-projected). Flat string[] per ADR-0129 D1; ADR-0131 class A.',
396
+ example: ['Alipay', 'WeChat Pay'],
397
+ type: 'array',
398
+ items: {
399
+ type: 'string'
400
+ }
401
+ },
402
+ searchTerms: {
403
+ description:
404
+ 'Locale-projected search synonyms (e.g. the zh bank-card / debit-card everyday terms for the checking account). Pure-locale projection — absent when the locale has no seeded synonyms; English fallback rides the authored aliases field. Search-only vocabulary, not the NLP routing corpus (#698, ADR-0131 fourth-class adjudication).',
405
+ example: ['yinhangka', 'jiejika'],
406
+ type: 'array',
407
+ items: {
408
+ type: 'string'
409
+ }
410
+ },
411
+ currency: {
412
+ type: 'string',
413
+ description:
414
+ 'Product denomination as a 3-letter ISO 4217 code, authored market data delivered verbatim (not localized, not xlf-managed). ADR-0131 class A. Absent = single-currency not asserted — consumers fall back to their own region currency (#714).',
415
+ example: 'HKD'
416
+ },
340
417
  description: {
341
418
  type: 'string',
342
- description: 'Account description (stable semantics only)',
419
+ description:
420
+ 'Account description (stable semantics only). Mixed-language contract: universal rows project to the request locale via the accountDesc xlf axis with an en fallback (ADR-0131 class P, ADR-0132; unseeded locales falling back to English are expected); regional rows deliver the authored market language (ADR-0131 class A, verbatim, never xlf-managed).',
343
421
  example: 'ICBC checking account for daily transactions'
344
422
  },
345
423
  tags: {
346
- description: 'Account tags for categorization',
424
+ description:
425
+ 'Account tags for categorization — structured metadata delivered verbatim (not localized, not xlf-managed). ADR-0131 class A.',
347
426
  example: ['bank', 'checking', 'primary'],
348
427
  type: 'array',
349
428
  items: {
@@ -354,9 +433,47 @@ export const $AccountStandardResponseDto = {
354
433
  type: 'string',
355
434
  description: 'Icon identifier for UI display',
356
435
  example: 'bank-icbc'
436
+ },
437
+ productCategory: {
438
+ type: 'string',
439
+ description:
440
+ 'Onboarding product category (coarse grouping derived from assetSubClass)',
441
+ enum: [
442
+ 'cash',
443
+ 'investment',
444
+ 'credit_card',
445
+ 'loan',
446
+ 'payable_tax',
447
+ 'other'
448
+ ],
449
+ example: 'investment'
450
+ },
451
+ assetClass: {
452
+ type: 'string',
453
+ description:
454
+ 'Asset class (LIQUIDITY/EQUITY/.../LIABILITY), derived at read time from classification rules',
455
+ enum: [
456
+ 'LIQUIDITY',
457
+ 'EQUITY',
458
+ 'FIXED_INCOME',
459
+ 'PRECIOUS_METALS',
460
+ 'COMMODITY',
461
+ 'INSURANCE',
462
+ 'ALTERNATIVE_INVESTMENT',
463
+ 'PERSONAL_ASSETS',
464
+ 'LIABILITY',
465
+ 'REAL_ESTATE',
466
+ 'INDEX'
467
+ ]
468
+ },
469
+ assetSubClass: {
470
+ type: 'string',
471
+ description:
472
+ 'Asset sub-class (product type, derived at read time from classification rules)',
473
+ example: 'STOCK'
357
474
  }
358
475
  },
359
- required: ['path', 'type', 'description', 'tags', 'icon']
476
+ required: ['path', 'type', 'description', 'tags', 'icon', 'productCategory']
360
477
  } as const;
361
478
 
362
479
  export const $AccountStandardListResponseDto = {
@@ -417,7 +534,10 @@ export const $RegionConfigDto = {
417
534
  },
418
535
  locale: {
419
536
  type: 'string',
420
- example: 'de-DE'
537
+ example: 'de-DE',
538
+ pattern: '^[a-z]{2,8}-[A-Z]{2}$',
539
+ description:
540
+ "Region-qualified BCP-47 tag whose region subtag equals the region's own ISO 3166-1 code (e.g., ja-JP, zh-CN, zh-HK)"
421
541
  }
422
542
  },
423
543
  required: ['currency', 'dateFormat', 'locale']
@@ -430,6 +550,12 @@ export const $RegionInfoDto = {
430
550
  type: 'string',
431
551
  example: 'de'
432
552
  },
553
+ open: {
554
+ type: 'boolean',
555
+ example: true,
556
+ description:
557
+ 'Whether the region is open (has a ready regional account template). Not-yet-open regions still return identity metadata and degrade to the universal-only catalog.'
558
+ },
433
559
  displayName: {
434
560
  type: 'string',
435
561
  example: 'Germany'
@@ -448,7 +574,7 @@ export const $RegionInfoDto = {
448
574
  $ref: '#/components/schemas/RegionConfigDto'
449
575
  }
450
576
  },
451
- required: ['code', 'displayName', 'chain', 'config']
577
+ required: ['code', 'open', 'displayName', 'chain', 'config']
452
578
  } as const;
453
579
 
454
580
  export const $RegionsMetadataResponseDto = {
@@ -695,7 +821,7 @@ export const $PostingResponseDto = {
695
821
  units: {
696
822
  type: 'string',
697
823
  description:
698
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
824
+ '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.',
699
825
  example: '100.50'
700
826
  },
701
827
  currency: {
@@ -1061,7 +1187,7 @@ export const $PostingDetailDto = {
1061
1187
  units: {
1062
1188
  type: 'string',
1063
1189
  description:
1064
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
1190
+ '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.',
1065
1191
  example: '100.50'
1066
1192
  },
1067
1193
  currency: {
@@ -1245,6 +1371,147 @@ export const $TransactionDetailDto = {
1245
1371
  ]
1246
1372
  } as const;
1247
1373
 
1374
+ export const $TransactionListItemDto = {
1375
+ type: 'object',
1376
+ properties: {
1377
+ id: {
1378
+ type: 'string',
1379
+ description: 'Transaction ID',
1380
+ example: 'clh1234567890abcdef'
1381
+ },
1382
+ date: {
1383
+ type: 'string',
1384
+ description: 'Transaction date',
1385
+ example: '2024-11-28'
1386
+ },
1387
+ flag: {
1388
+ type: 'string',
1389
+ description: 'Transaction flag',
1390
+ enum: [
1391
+ 'CLEARED',
1392
+ 'PENDING',
1393
+ 'PADDING',
1394
+ 'SUMMARIZE',
1395
+ 'TRANSFER',
1396
+ 'CONVERSIONS'
1397
+ ],
1398
+ example: 'CLEARED'
1399
+ },
1400
+ customFlag: {
1401
+ type: 'string',
1402
+ description: 'Custom flag (if not using standard flags)',
1403
+ example: 'R'
1404
+ },
1405
+ payee: {
1406
+ type: 'string',
1407
+ description: 'Payee name',
1408
+ example: 'Whole Foods Market'
1409
+ },
1410
+ narration: {
1411
+ type: 'string',
1412
+ description: 'Transaction narration',
1413
+ example: 'Grocery shopping'
1414
+ },
1415
+ tags: {
1416
+ description: 'Transaction tags',
1417
+ example: ['groceries'],
1418
+ type: 'array',
1419
+ items: {
1420
+ type: 'string'
1421
+ }
1422
+ },
1423
+ links: {
1424
+ description: 'Transaction links',
1425
+ example: ['invoice-2024-001'],
1426
+ type: 'array',
1427
+ items: {
1428
+ type: 'string'
1429
+ }
1430
+ },
1431
+ meta: {
1432
+ type: 'object',
1433
+ description: 'Transaction metadata'
1434
+ },
1435
+ status: {
1436
+ type: 'string',
1437
+ description: 'Transaction status',
1438
+ enum: ['ACTIVE', 'VOIDED', 'SUPERSEDED'],
1439
+ example: 'ACTIVE'
1440
+ },
1441
+ sourceType: {
1442
+ type: 'string',
1443
+ description:
1444
+ 'Source type (free-form string from transaction metadata, e.g. import, api)'
1445
+ },
1446
+ sourcePlatform: {
1447
+ type: 'string',
1448
+ description: 'Source platform (e.g., alipay, wechat)',
1449
+ example: 'alipay'
1450
+ },
1451
+ postings: {
1452
+ description: 'Transaction postings',
1453
+ type: 'array',
1454
+ items: {
1455
+ $ref: '#/components/schemas/PostingDetailDto'
1456
+ }
1457
+ },
1458
+ createdAt: {
1459
+ type: 'string',
1460
+ description: 'Created at timestamp',
1461
+ example: '2024-11-28T10:30:00.000Z'
1462
+ },
1463
+ voidedAt: {
1464
+ type: 'string',
1465
+ description: 'Voided at timestamp (if voided)',
1466
+ example: '2024-11-29T15:00:00.000Z'
1467
+ },
1468
+ voidedBy: {
1469
+ type: 'string',
1470
+ description: 'User ID who voided this transaction',
1471
+ example: 'clh1234567890abcdef'
1472
+ },
1473
+ correctionReason: {
1474
+ type: 'string',
1475
+ description: 'Correction reason (if voided or superseded)',
1476
+ example: 'Duplicate entry'
1477
+ },
1478
+ supersededBy: {
1479
+ type: 'string',
1480
+ description:
1481
+ 'ID of the transaction that supersedes this one (set when status=SUPERSEDED)',
1482
+ example: 'clh1234567890abcdef'
1483
+ },
1484
+ originalTxn: {
1485
+ type: 'string',
1486
+ description:
1487
+ 'ID of the transaction this one corrected/replaced (back-link on the replacement)',
1488
+ example: 'clh1234567890abcdef'
1489
+ },
1490
+ viewpointAmount: {
1491
+ type: 'string',
1492
+ description:
1493
+ '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.',
1494
+ example: '10000.00'
1495
+ },
1496
+ viewpointCurrency: {
1497
+ type: 'string',
1498
+ description:
1499
+ 'Currency of viewpointAmount. A row spanning multiple currencies takes the largest-magnitude currency group (known simplification, ADR-0126).',
1500
+ example: 'CNY'
1501
+ }
1502
+ },
1503
+ required: [
1504
+ 'id',
1505
+ 'date',
1506
+ 'narration',
1507
+ 'tags',
1508
+ 'links',
1509
+ 'status',
1510
+ 'postings',
1511
+ 'createdAt'
1512
+ ]
1513
+ } as const;
1514
+
1248
1515
  export const $BalanceByCurrencyDto = {
1249
1516
  type: 'object',
1250
1517
  properties: {
@@ -1290,7 +1557,7 @@ export const $TransactionListSummaryDto = {
1290
1557
  totalAmount: {
1291
1558
  type: 'string',
1292
1559
  description:
1293
- '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.',
1560
+ '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.',
1294
1561
  example: '-6000.00'
1295
1562
  },
1296
1563
  currency: {
@@ -1316,6 +1583,26 @@ export const $TransactionListSummaryDto = {
1316
1583
  required: ['totalAmount', 'currency', 'balanceByCurrency']
1317
1584
  } as const;
1318
1585
 
1586
+ export const $TransactionListViewpointDto = {
1587
+ type: 'object',
1588
+ properties: {
1589
+ type: {
1590
+ type: 'string',
1591
+ description:
1592
+ 'Viewpoint type (only category drill-down carries a viewpoint today)',
1593
+ enum: ['category'],
1594
+ example: 'category'
1595
+ },
1596
+ flow: {
1597
+ type: 'string',
1598
+ description: 'Flow root the category account set is restricted to',
1599
+ enum: ['income', 'expense'],
1600
+ example: 'expense'
1601
+ }
1602
+ },
1603
+ required: ['type', 'flow']
1604
+ } as const;
1605
+
1319
1606
  export const $TransactionListResponseDto = {
1320
1607
  type: 'object',
1321
1608
  properties: {
@@ -1323,7 +1610,7 @@ export const $TransactionListResponseDto = {
1323
1610
  description: 'List of transactions',
1324
1611
  type: 'array',
1325
1612
  items: {
1326
- $ref: '#/components/schemas/TransactionDetailDto'
1613
+ $ref: '#/components/schemas/TransactionListItemDto'
1327
1614
  }
1328
1615
  },
1329
1616
  total: {
@@ -1349,6 +1636,15 @@ export const $TransactionListResponseDto = {
1349
1636
  $ref: '#/components/schemas/TransactionListSummaryDto'
1350
1637
  }
1351
1638
  ]
1639
+ },
1640
+ viewpoint: {
1641
+ description:
1642
+ '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).',
1643
+ allOf: [
1644
+ {
1645
+ $ref: '#/components/schemas/TransactionListViewpointDto'
1646
+ }
1647
+ ]
1352
1648
  }
1353
1649
  },
1354
1650
  required: ['data', 'total', 'limit', 'offset']
@@ -2259,10 +2555,10 @@ export const $UpdatePayeeDto = {
2259
2555
  meta: {
2260
2556
  type: 'object',
2261
2557
  description:
2262
- 'Metadata for extended information (location, notes, contact info, etc.). Will merge with existing metadata.',
2558
+ 'Metadata for extended information (location, notes, contact info, etc.)',
2263
2559
  example: {
2264
2560
  location: 'Zhongguancun',
2265
- note: 'Updated note',
2561
+ note: 'Near subway station',
2266
2562
  favorite: true
2267
2563
  }
2268
2564
  },
@@ -2823,29 +3119,308 @@ export const $UpdateCommodityDto = {
2823
3119
  }
2824
3120
  } as const;
2825
3121
 
2826
- export const $CreateBeanPriceDto = {
3122
+ export const $CurrencyBalanceDto = {
2827
3123
  type: 'object',
2828
3124
  properties: {
2829
3125
  currency: {
2830
3126
  type: 'string',
2831
- description: 'Currency being priced (e.g., USD, AAPL, BTC)',
2832
- example: 'USD'
2833
- },
2834
- quoteCurrency: {
2835
- type: 'string',
2836
- description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
3127
+ description: 'ISO 4217 currency code',
2837
3128
  example: 'CNY'
2838
3129
  },
2839
- amount: {
2840
- type: 'number',
2841
- description:
2842
- 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
2843
- example: 175.5,
2844
- minimum: 0
2845
- },
3130
+ balance: {
3131
+ type: 'string',
3132
+ description: 'Balance amount',
3133
+ example: '500000.00'
3134
+ }
3135
+ },
3136
+ required: ['currency', 'balance']
3137
+ } as const;
3138
+
3139
+ export const $TimeSeriesPointDto = {
3140
+ type: 'object',
3141
+ properties: {
2846
3142
  date: {
2847
3143
  type: 'string',
2848
- description: 'Price date (ISO 8601 format)',
3144
+ description: 'Date in YYYY-MM-DD format',
3145
+ example: '2024-06-15'
3146
+ },
3147
+ value: {
3148
+ type: 'string',
3149
+ description: 'Value at this date (in base currency)',
3150
+ example: '500000.00'
3151
+ },
3152
+ change: {
3153
+ type: 'string',
3154
+ description: 'Change from previous point',
3155
+ example: '5000.00'
3156
+ },
3157
+ assets: {
3158
+ type: 'string',
3159
+ description: 'Total assets at this date (in base currency)',
3160
+ example: '494338.00'
3161
+ },
3162
+ liabilities: {
3163
+ type: 'string',
3164
+ description: 'Total liabilities at this date (in base currency)',
3165
+ example: '310098.00'
3166
+ },
3167
+ byCurrency: {
3168
+ description: 'Multi-currency breakdown for this point',
3169
+ type: 'array',
3170
+ items: {
3171
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3172
+ }
3173
+ }
3174
+ },
3175
+ required: ['date', 'value']
3176
+ } as const;
3177
+
3178
+ export const $TrendSummaryDto = {
3179
+ type: 'object',
3180
+ properties: {
3181
+ startValue: {
3182
+ type: 'string',
3183
+ description: 'Value at start of period',
3184
+ example: '450000.00'
3185
+ },
3186
+ endValue: {
3187
+ type: 'string',
3188
+ description: 'Value at end of period',
3189
+ example: '500000.00'
3190
+ },
3191
+ totalChange: {
3192
+ type: 'string',
3193
+ description: 'Total change over period',
3194
+ example: '50000.00'
3195
+ },
3196
+ totalChangePercentage: {
3197
+ type: 'string',
3198
+ description: 'Total change percentage',
3199
+ example: '+11.11%'
3200
+ }
3201
+ },
3202
+ required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
3203
+ } as const;
3204
+
3205
+ export const $MultiCurrencyPointDto = {
3206
+ type: 'object',
3207
+ properties: {
3208
+ date: {
3209
+ type: 'string',
3210
+ description: 'Date in YYYY-MM-DD format',
3211
+ example: '2024-06-15'
3212
+ },
3213
+ byCurrency: {
3214
+ description: 'Balances by currency',
3215
+ type: 'array',
3216
+ items: {
3217
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3218
+ }
3219
+ }
3220
+ },
3221
+ required: ['date', 'byCurrency']
3222
+ } as const;
3223
+
3224
+ export const $PortfolioTrendsResponseDto = {
3225
+ type: 'object',
3226
+ properties: {
3227
+ series: {
3228
+ description: 'Time series data points',
3229
+ type: 'array',
3230
+ items: {
3231
+ $ref: '#/components/schemas/TimeSeriesPointDto'
3232
+ }
3233
+ },
3234
+ summary: {
3235
+ description: 'Period summary',
3236
+ allOf: [
3237
+ {
3238
+ $ref: '#/components/schemas/TrendSummaryDto'
3239
+ }
3240
+ ]
3241
+ },
3242
+ period: {
3243
+ type: 'string',
3244
+ description: 'Period requested',
3245
+ example: '6m'
3246
+ },
3247
+ granularity: {
3248
+ type: 'string',
3249
+ description: 'Data granularity',
3250
+ example: 'month'
3251
+ },
3252
+ currency: {
3253
+ type: 'string',
3254
+ description: 'Base currency for converted values',
3255
+ example: 'CNY'
3256
+ },
3257
+ byCurrency: {
3258
+ description:
3259
+ 'Multi-currency time series (each point has currency breakdown)',
3260
+ type: 'array',
3261
+ items: {
3262
+ $ref: '#/components/schemas/MultiCurrencyPointDto'
3263
+ }
3264
+ },
3265
+ warnings: {
3266
+ description: 'Exchange rate warnings',
3267
+ type: 'array',
3268
+ items: {
3269
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3270
+ }
3271
+ }
3272
+ },
3273
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3274
+ } as const;
3275
+
3276
+ export const $CashFlowPointDto = {
3277
+ type: 'object',
3278
+ properties: {
3279
+ month: {
3280
+ type: 'string',
3281
+ description: 'Month key (YYYY-MM)',
3282
+ example: '2024-03'
3283
+ },
3284
+ income: {
3285
+ type: 'string',
3286
+ description: 'Income in base currency (absolute, converted)',
3287
+ example: '10000.00'
3288
+ },
3289
+ expense: {
3290
+ type: 'string',
3291
+ description: 'Expense in base currency (absolute, converted)',
3292
+ example: '5000.00'
3293
+ },
3294
+ netSavings: {
3295
+ type: 'string',
3296
+ description: 'netSavings = income − expense (savings positive)',
3297
+ example: '5000.00'
3298
+ }
3299
+ },
3300
+ required: ['month', 'income', 'expense', 'netSavings']
3301
+ } as const;
3302
+
3303
+ export const $CashFlowTrendSummaryDto = {
3304
+ type: 'object',
3305
+ properties: {
3306
+ totalIncome: {
3307
+ type: 'string',
3308
+ description: 'Total income across the period',
3309
+ example: '60000.00'
3310
+ },
3311
+ totalExpense: {
3312
+ type: 'string',
3313
+ description: 'Total expense across the period',
3314
+ example: '30000.00'
3315
+ },
3316
+ totalNetSavings: {
3317
+ type: 'string',
3318
+ description: 'income − expense across the period',
3319
+ example: '30000.00'
3320
+ },
3321
+ averageMonthlyNetSavings: {
3322
+ type: 'string',
3323
+ description:
3324
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
3325
+ example: '5000.00'
3326
+ }
3327
+ },
3328
+ required: [
3329
+ 'totalIncome',
3330
+ 'totalExpense',
3331
+ 'totalNetSavings',
3332
+ 'averageMonthlyNetSavings'
3333
+ ]
3334
+ } as const;
3335
+
3336
+ export const $CashFlowTrendsResponseDto = {
3337
+ type: 'object',
3338
+ properties: {
3339
+ series: {
3340
+ description:
3341
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
3342
+ type: 'array',
3343
+ items: {
3344
+ $ref: '#/components/schemas/CashFlowPointDto'
3345
+ }
3346
+ },
3347
+ summary: {
3348
+ description: 'Period totals',
3349
+ allOf: [
3350
+ {
3351
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
3352
+ }
3353
+ ]
3354
+ },
3355
+ period: {
3356
+ type: 'string',
3357
+ description: 'Period requested',
3358
+ example: '6m'
3359
+ },
3360
+ granularity: {
3361
+ type: 'string',
3362
+ description: 'Data granularity (v1 returns month buckets)',
3363
+ example: 'month'
3364
+ },
3365
+ currency: {
3366
+ type: 'string',
3367
+ description: 'Base currency for converted values',
3368
+ example: 'CNY'
3369
+ },
3370
+ warnings: {
3371
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
3372
+ type: 'array',
3373
+ items: {
3374
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3375
+ }
3376
+ }
3377
+ },
3378
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3379
+ } as const;
3380
+
3381
+ export const $GenerateSnapshotBody = {
3382
+ type: 'object',
3383
+ properties: {}
3384
+ } as const;
3385
+
3386
+ export const $GenerateSnapshotResponse = {
3387
+ type: 'object',
3388
+ properties: {}
3389
+ } as const;
3390
+
3391
+ export const $BackfillSnapshotsBody = {
3392
+ type: 'object',
3393
+ properties: {}
3394
+ } as const;
3395
+
3396
+ export const $BackfillSnapshotsResponse = {
3397
+ type: 'object',
3398
+ properties: {}
3399
+ } as const;
3400
+
3401
+ export const $CreateBeanPriceDto = {
3402
+ type: 'object',
3403
+ properties: {
3404
+ currency: {
3405
+ type: 'string',
3406
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3407
+ example: 'USD'
3408
+ },
3409
+ quoteCurrency: {
3410
+ type: 'string',
3411
+ description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
3412
+ example: 'CNY'
3413
+ },
3414
+ amount: {
3415
+ type: 'number',
3416
+ description:
3417
+ 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
3418
+ example: 175.5,
3419
+ minimum: 0
3420
+ },
3421
+ date: {
3422
+ type: 'string',
3423
+ description: 'Price date (ISO 8601 format)',
2849
3424
  example: '2024-11-05'
2850
3425
  },
2851
3426
  metadata: {
@@ -2980,6 +3555,218 @@ export const $UpdateBeanPriceDto = {
2980
3555
  }
2981
3556
  } as const;
2982
3557
 
3558
+ export const $DeleteOwnUserDto = {
3559
+ type: 'object',
3560
+ properties: {
3561
+ accessToken: {
3562
+ type: 'string',
3563
+ description: 'Access token for user verification',
3564
+ example: 'abc123xyz'
3565
+ }
3566
+ },
3567
+ required: ['accessToken']
3568
+ } as const;
3569
+
3570
+ export const $UserSettingsResponseDto = {
3571
+ type: 'object',
3572
+ properties: {
3573
+ baseCurrency: {
3574
+ type: 'string',
3575
+ description:
3576
+ 'Stored base currency choice (ISO 4217) for net-worth/report aggregation. null = user never chose; aggregates fall back to the region default at display time (#713).',
3577
+ example: 'USD',
3578
+ nullable: true
3579
+ }
3580
+ },
3581
+ required: ['baseCurrency']
3582
+ } as const;
3583
+
3584
+ export const $UserResponseDto = {
3585
+ type: 'object',
3586
+ properties: {
3587
+ id: {
3588
+ type: 'string',
3589
+ description: 'User ID'
3590
+ },
3591
+ role: {
3592
+ type: 'string',
3593
+ description: 'Assigned user role'
3594
+ },
3595
+ permissions: {
3596
+ description: 'Permission strings',
3597
+ type: 'array',
3598
+ items: {
3599
+ type: 'string'
3600
+ }
3601
+ },
3602
+ settings: {
3603
+ description: 'User settings',
3604
+ allOf: [
3605
+ {
3606
+ $ref: '#/components/schemas/UserSettingsResponseDto'
3607
+ }
3608
+ ]
3609
+ }
3610
+ },
3611
+ required: ['id', 'role', 'permissions', 'settings']
3612
+ } as const;
3613
+
3614
+ export const $SignupDto = {
3615
+ type: 'object',
3616
+ properties: {
3617
+ turnstileToken: {
3618
+ type: 'string',
3619
+ description:
3620
+ 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
3621
+ example: '0.abc123def456...'
3622
+ }
3623
+ }
3624
+ } as const;
3625
+
3626
+ export const $SignupResponseDto = {
3627
+ type: 'object',
3628
+ properties: {
3629
+ authToken: {
3630
+ type: 'string',
3631
+ description: 'JWT auth token',
3632
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
3633
+ },
3634
+ accessToken: {
3635
+ type: 'string',
3636
+ description: 'Auto-generated access token'
3637
+ },
3638
+ role: {
3639
+ type: 'string',
3640
+ description: 'Assigned user role',
3641
+ enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
3642
+ }
3643
+ },
3644
+ required: ['authToken', 'accessToken', 'role']
3645
+ } as const;
3646
+
3647
+ export const $UpdateUserSettingDto = {
3648
+ type: 'object',
3649
+ properties: {
3650
+ secId: {
3651
+ type: 'number',
3652
+ description: 'Security ID'
3653
+ },
3654
+ annualInterestRate: {
3655
+ type: 'number',
3656
+ description: 'Annual interest rate',
3657
+ example: 0.05
3658
+ },
3659
+ currency: {
3660
+ type: 'string',
3661
+ description: 'Currency code',
3662
+ example: 'USD'
3663
+ },
3664
+ baseCurrency: {
3665
+ type: 'string',
3666
+ description: 'Base currency code',
3667
+ example: 'USD'
3668
+ },
3669
+ benchmark: {
3670
+ type: 'string',
3671
+ description: 'Benchmark symbol',
3672
+ example: 'SPY'
3673
+ },
3674
+ colorScheme: {
3675
+ type: 'string',
3676
+ description: 'Color scheme',
3677
+ enum: ['DARK', 'LIGHT']
3678
+ },
3679
+ dateRange: {
3680
+ type: 'string',
3681
+ description: 'Date range filter',
3682
+ example: '1y'
3683
+ },
3684
+ emergencyFund: {
3685
+ type: 'number',
3686
+ description: 'Emergency fund amount',
3687
+ example: 10000
3688
+ },
3689
+ 'filters.accounts': {
3690
+ description: 'Account filter IDs',
3691
+ type: 'array',
3692
+ items: {
3693
+ type: 'string'
3694
+ }
3695
+ },
3696
+ 'filters.assetClasses': {
3697
+ description: 'Asset class filters',
3698
+ type: 'array',
3699
+ items: {
3700
+ type: 'string'
3701
+ }
3702
+ },
3703
+ 'filters.dataSource': {
3704
+ type: 'string',
3705
+ description: 'Data source filter'
3706
+ },
3707
+ 'filters.symbol': {
3708
+ type: 'string',
3709
+ description: 'Symbol filter'
3710
+ },
3711
+ 'filters.tags': {
3712
+ description: 'Tag filters',
3713
+ type: 'array',
3714
+ items: {
3715
+ type: 'string'
3716
+ }
3717
+ },
3718
+ isExperimentalFeatures: {
3719
+ type: 'boolean',
3720
+ description: 'Enable experimental features'
3721
+ },
3722
+ isRestrictedView: {
3723
+ type: 'boolean',
3724
+ description: 'Enable restricted view mode'
3725
+ },
3726
+ language: {
3727
+ type: 'string',
3728
+ description: 'Language code',
3729
+ example: 'en'
3730
+ },
3731
+ locale: {
3732
+ type: 'string',
3733
+ description: 'Locale code',
3734
+ example: 'en-US'
3735
+ },
3736
+ projectedTotalAmount: {
3737
+ type: 'number',
3738
+ description: 'Projected total amount',
3739
+ example: 1000000
3740
+ },
3741
+ retirementDate: {
3742
+ type: 'string',
3743
+ description: 'Retirement date in ISO 8601 format',
3744
+ example: '2050-01-01'
3745
+ },
3746
+ savingsRate: {
3747
+ type: 'number',
3748
+ description: 'Savings rate percentage',
3749
+ example: 0.2
3750
+ },
3751
+ viewMode: {
3752
+ type: 'string',
3753
+ description: 'View mode',
3754
+ enum: ['DEFAULT', 'ZEN']
3755
+ }
3756
+ }
3757
+ } as const;
3758
+
3759
+ export const $UpdatePropertyDto = {
3760
+ type: 'object',
3761
+ properties: {
3762
+ value: {
3763
+ type: 'string',
3764
+ description: 'Property value'
3765
+ }
3766
+ },
3767
+ required: ['value']
3768
+ } as const;
3769
+
2983
3770
  export const $CreateRecurringRuleDto = {
2984
3771
  type: 'object',
2985
3772
  properties: {
@@ -3025,7 +3812,6 @@ export const $CreateRecurringRuleDto = {
3025
3812
  currency: {
3026
3813
  type: 'string',
3027
3814
  description: 'Currency code',
3028
- default: 'CNY',
3029
3815
  maxLength: 10
3030
3816
  },
3031
3817
  matchPayeePattern: {
@@ -3073,7 +3859,6 @@ export const $CreateRecurringRuleDto = {
3073
3859
  'name',
3074
3860
  'frequency',
3075
3861
  'expectedAmount',
3076
- 'currency',
3077
3862
  'matchAmountTolerance',
3078
3863
  'autoCreate'
3079
3864
  ]
@@ -3095,7 +3880,7 @@ export const $RecurringRuleResponseDto = {
3095
3880
  description: 'Rule name'
3096
3881
  },
3097
3882
  icon: {
3098
- type: 'object',
3883
+ type: 'string',
3099
3884
  description: 'Icon emoji'
3100
3885
  },
3101
3886
  frequency: {
@@ -3107,11 +3892,11 @@ export const $RecurringRuleResponseDto = {
3107
3892
  description: 'Expected amount'
3108
3893
  },
3109
3894
  expectedDay: {
3110
- type: 'object',
3895
+ type: 'number',
3111
3896
  description: 'Expected day of month'
3112
3897
  },
3113
3898
  customIntervalDays: {
3114
- type: 'object',
3899
+ type: 'number',
3115
3900
  description: 'Custom interval in days'
3116
3901
  },
3117
3902
  currency: {
@@ -3119,7 +3904,7 @@ export const $RecurringRuleResponseDto = {
3119
3904
  description: 'Currency code'
3120
3905
  },
3121
3906
  matchPayeePattern: {
3122
- type: 'object',
3907
+ type: 'string',
3123
3908
  description: 'Payee matching pattern'
3124
3909
  },
3125
3910
  matchAmountTolerance: {
@@ -3127,15 +3912,15 @@ export const $RecurringRuleResponseDto = {
3127
3912
  description: 'Amount tolerance percentage'
3128
3913
  },
3129
3914
  defaultExpenseAccount: {
3130
- type: 'object',
3915
+ type: 'string',
3131
3916
  description: 'Default expense account'
3132
3917
  },
3133
3918
  defaultPaymentAccount: {
3134
- type: 'object',
3919
+ type: 'string',
3135
3920
  description: 'Default payment account'
3136
3921
  },
3137
3922
  defaultPayee: {
3138
- type: 'object',
3923
+ type: 'string',
3139
3924
  description: 'Default payee'
3140
3925
  },
3141
3926
  isActive: {
@@ -3147,7 +3932,7 @@ export const $RecurringRuleResponseDto = {
3147
3932
  description: 'Rule start date (YYYY-MM-DD)'
3148
3933
  },
3149
3934
  endDate: {
3150
- type: 'object',
3935
+ type: 'string',
3151
3936
  description: 'Rule end date (YYYY-MM-DD)'
3152
3937
  },
3153
3938
  autoCreate: {
@@ -3155,7 +3940,7 @@ export const $RecurringRuleResponseDto = {
3155
3940
  description: 'Auto-create transaction on expected date'
3156
3941
  },
3157
3942
  lastOccurrence: {
3158
- type: 'object',
3943
+ type: 'string',
3159
3944
  description: 'Last matched occurrence date (YYYY-MM-DD)'
3160
3945
  },
3161
3946
  totalCount: {
@@ -3237,7 +4022,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3237
4022
  description: 'Rule name'
3238
4023
  },
3239
4024
  icon: {
3240
- type: 'object',
4025
+ type: 'string',
3241
4026
  description: 'Icon emoji'
3242
4027
  },
3243
4028
  frequency: {
@@ -3249,11 +4034,11 @@ export const $RecurringRuleWithStatsResponseDto = {
3249
4034
  description: 'Expected amount'
3250
4035
  },
3251
4036
  expectedDay: {
3252
- type: 'object',
4037
+ type: 'number',
3253
4038
  description: 'Expected day of month'
3254
4039
  },
3255
4040
  customIntervalDays: {
3256
- type: 'object',
4041
+ type: 'number',
3257
4042
  description: 'Custom interval in days'
3258
4043
  },
3259
4044
  currency: {
@@ -3261,7 +4046,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3261
4046
  description: 'Currency code'
3262
4047
  },
3263
4048
  matchPayeePattern: {
3264
- type: 'object',
4049
+ type: 'string',
3265
4050
  description: 'Payee matching pattern'
3266
4051
  },
3267
4052
  matchAmountTolerance: {
@@ -3269,15 +4054,15 @@ export const $RecurringRuleWithStatsResponseDto = {
3269
4054
  description: 'Amount tolerance percentage'
3270
4055
  },
3271
4056
  defaultExpenseAccount: {
3272
- type: 'object',
4057
+ type: 'string',
3273
4058
  description: 'Default expense account'
3274
4059
  },
3275
4060
  defaultPaymentAccount: {
3276
- type: 'object',
4061
+ type: 'string',
3277
4062
  description: 'Default payment account'
3278
4063
  },
3279
4064
  defaultPayee: {
3280
- type: 'object',
4065
+ type: 'string',
3281
4066
  description: 'Default payee'
3282
4067
  },
3283
4068
  isActive: {
@@ -3289,7 +4074,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3289
4074
  description: 'Rule start date (YYYY-MM-DD)'
3290
4075
  },
3291
4076
  endDate: {
3292
- type: 'object',
4077
+ type: 'string',
3293
4078
  description: 'Rule end date (YYYY-MM-DD)'
3294
4079
  },
3295
4080
  autoCreate: {
@@ -3297,7 +4082,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3297
4082
  description: 'Auto-create transaction on expected date'
3298
4083
  },
3299
4084
  lastOccurrence: {
3300
- type: 'object',
4085
+ type: 'string',
3301
4086
  description: 'Last matched occurrence date (YYYY-MM-DD)'
3302
4087
  },
3303
4088
  totalCount: {
@@ -3323,7 +4108,7 @@ export const $RecurringRuleWithStatsResponseDto = {
3323
4108
  description: 'Number of overdue expected transactions'
3324
4109
  },
3325
4110
  nextExpectedDate: {
3326
- type: 'object',
4111
+ type: 'string',
3327
4112
  description: 'Next expected date (YYYY-MM-DD)'
3328
4113
  },
3329
4114
  totalAmount: {
@@ -3339,11 +4124,11 @@ export const $RecurringRuleWithStatsResponseDto = {
3339
4124
  description: 'Number of matched transactions'
3340
4125
  },
3341
4126
  firstDate: {
3342
- type: 'object',
4127
+ type: 'string',
3343
4128
  description: 'First matched transaction date (YYYY-MM-DD)'
3344
4129
  },
3345
4130
  lastDate: {
3346
- type: 'object',
4131
+ type: 'string',
3347
4132
  description: 'Last matched transaction date (YYYY-MM-DD)'
3348
4133
  },
3349
4134
  variance: {
@@ -3384,7 +4169,7 @@ export const $UpdateRecurringRuleDto = {
3384
4169
  properties: {
3385
4170
  name: {
3386
4171
  type: 'string',
3387
- description: 'Rule name',
4172
+ description: 'Rule name (unique per user)',
3388
4173
  maxLength: 100
3389
4174
  },
3390
4175
  icon: {
@@ -3407,7 +4192,7 @@ export const $UpdateRecurringRuleDto = {
3407
4192
  },
3408
4193
  expectedAmount: {
3409
4194
  type: 'number',
3410
- description: 'Expected amount',
4195
+ description: 'Expected amount (positive number)',
3411
4196
  minimum: 0
3412
4197
  },
3413
4198
  expectedDay: {
@@ -3416,11 +4201,6 @@ export const $UpdateRecurringRuleDto = {
3416
4201
  minimum: 1,
3417
4202
  maximum: 31
3418
4203
  },
3419
- customIntervalDays: {
3420
- type: 'number',
3421
- description: 'Custom interval in days',
3422
- minimum: 1
3423
- },
3424
4204
  currency: {
3425
4205
  type: 'string',
3426
4206
  description: 'Currency code',
@@ -3428,41 +4208,48 @@ export const $UpdateRecurringRuleDto = {
3428
4208
  },
3429
4209
  matchPayeePattern: {
3430
4210
  type: 'string',
3431
- description: 'Payee matching pattern',
4211
+ description: 'Payee matching pattern (supports wildcards)',
3432
4212
  maxLength: 200
3433
4213
  },
3434
4214
  matchAmountTolerance: {
3435
4215
  type: 'number',
3436
4216
  description: 'Amount tolerance percentage (0-1)',
4217
+ default: 0.075,
3437
4218
  minimum: 0,
3438
4219
  maximum: 1
3439
4220
  },
3440
4221
  defaultExpenseAccount: {
3441
4222
  type: 'string',
3442
- description: 'Default expense account',
4223
+ description: 'Default expense account for auto-create',
3443
4224
  maxLength: 200
3444
4225
  },
3445
4226
  defaultPaymentAccount: {
3446
4227
  type: 'string',
3447
- description: 'Default payment account',
4228
+ description: 'Default payment account for auto-create',
3448
4229
  maxLength: 200
3449
4230
  },
3450
4231
  defaultPayee: {
3451
4232
  type: 'string',
3452
- description: 'Default payee',
4233
+ description: 'Default payee for auto-create',
3453
4234
  maxLength: 200
3454
4235
  },
3455
4236
  autoCreate: {
3456
4237
  type: 'boolean',
3457
- description: 'Auto-create transaction'
3458
- },
3459
- isActive: {
3460
- type: 'boolean',
3461
- description: 'Rule active status'
4238
+ description: 'Auto-create transaction when expected date arrives',
4239
+ default: false
3462
4240
  },
3463
4241
  endDate: {
3464
4242
  type: 'string',
3465
4243
  description: 'Rule end date (ISO format)'
4244
+ },
4245
+ customIntervalDays: {
4246
+ type: 'number',
4247
+ description: 'Custom interval in days',
4248
+ minimum: 1
4249
+ },
4250
+ isActive: {
4251
+ type: 'boolean',
4252
+ description: 'Rule active status'
3466
4253
  }
3467
4254
  }
3468
4255
  } as const;
@@ -3475,7 +4262,7 @@ export const $ExpectedTransactionRuleDto = {
3475
4262
  description: 'Rule name'
3476
4263
  },
3477
4264
  icon: {
3478
- type: 'object',
4265
+ type: 'string',
3479
4266
  description: 'Rule icon'
3480
4267
  },
3481
4268
  frequency: {
@@ -3518,15 +4305,15 @@ export const $ExpectedTransactionResponseDto = {
3518
4305
  description: 'Status (PENDING, COMPLETED, SKIPPED)'
3519
4306
  },
3520
4307
  matchedTransactionId: {
3521
- type: 'object',
4308
+ type: 'string',
3522
4309
  description: 'Matched transaction ID'
3523
4310
  },
3524
4311
  matchedAt: {
3525
- type: 'object',
4312
+ type: 'string',
3526
4313
  description: 'Match timestamp (ISO 8601)'
3527
4314
  },
3528
4315
  matchConfidence: {
3529
- type: 'object',
4316
+ type: 'number',
3530
4317
  description: 'Match confidence score (0-1)'
3531
4318
  },
3532
4319
  isOverdue: {
@@ -4310,7 +5097,8 @@ export const $UpdateTransactionRuleDto = {
4310
5097
  },
4311
5098
  matchLogic: {
4312
5099
  type: 'string',
4313
- enum: ['OR', 'AND']
5100
+ enum: ['OR', 'AND'],
5101
+ default: 'OR'
4314
5102
  },
4315
5103
  amountMin: {
4316
5104
  type: 'number',
@@ -4324,13 +5112,10 @@ export const $UpdateTransactionRuleDto = {
4324
5112
  },
4325
5113
  priority: {
4326
5114
  type: 'number',
5115
+ default: 50,
4327
5116
  minimum: 0,
4328
5117
  maximum: 1000
4329
5118
  },
4330
- enabled: {
4331
- type: 'boolean',
4332
- description: 'Enable or disable the rule'
4333
- },
4334
5119
  additionalTags: {
4335
5120
  items: {
4336
5121
  type: 'array'
@@ -4340,6 +5125,10 @@ export const $UpdateTransactionRuleDto = {
4340
5125
  },
4341
5126
  additionalMetadata: {
4342
5127
  type: 'object'
5128
+ },
5129
+ enabled: {
5130
+ type: 'boolean',
5131
+ description: 'Enable or disable the rule'
4343
5132
  }
4344
5133
  }
4345
5134
  } as const;
@@ -4400,151 +5189,67 @@ export const $TestRuleResponseDto = {
4400
5189
  required: ['ruleId', 'matches', 'confidence', 'matchDetails']
4401
5190
  } as const;
4402
5191
 
4403
- export const $DeleteOwnUserDto = {
4404
- type: 'object',
4405
- properties: {
4406
- accessToken: {
4407
- type: 'string',
4408
- description: 'Access token for user verification',
4409
- example: 'abc123xyz'
4410
- }
4411
- },
4412
- required: ['accessToken']
4413
- } as const;
4414
-
4415
- export const $SignupDto = {
4416
- type: 'object',
4417
- properties: {
4418
- turnstileToken: {
4419
- type: 'string',
4420
- description:
4421
- 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4422
- example: '0.abc123def456...'
4423
- }
4424
- }
4425
- } as const;
4426
-
4427
- export const $UpdateUserSettingDto = {
5192
+ export const $CategoryCatalogEntryDto = {
4428
5193
  type: 'object',
4429
5194
  properties: {
4430
- secId: {
4431
- type: 'number',
4432
- description: 'Security ID'
4433
- },
4434
- annualInterestRate: {
4435
- type: 'number',
4436
- description: 'Annual interest rate',
4437
- example: 0.05
4438
- },
4439
- currency: {
4440
- type: 'string',
4441
- description: 'Currency code',
4442
- example: 'USD'
4443
- },
4444
- baseCurrency: {
4445
- type: 'string',
4446
- description: 'Base currency code',
4447
- example: 'USD'
4448
- },
4449
- benchmark: {
5195
+ slug: {
4450
5196
  type: 'string',
4451
- description: 'Benchmark symbol',
4452
- example: 'SPY'
5197
+ description: 'Category slug (single source-of-truth)',
5198
+ example: 'food'
4453
5199
  },
4454
- colorScheme: {
5200
+ scenario: {
4455
5201
  type: 'string',
4456
- description: 'Color scheme',
4457
- enum: ['DARK', 'LIGHT']
5202
+ description: 'Display scenario group (maps to frontend picker _scenario)',
5203
+ enum: [
5204
+ 'expense',
5205
+ 'income',
5206
+ 'investment',
5207
+ 'banking',
5208
+ 'transfer',
5209
+ 'payment'
5210
+ ],
5211
+ example: 'expense'
4458
5212
  },
4459
- dateRange: {
5213
+ icon: {
4460
5214
  type: 'string',
4461
- description: 'Date range filter',
4462
- example: '1y'
4463
- },
4464
- emergencyFund: {
4465
- type: 'number',
4466
- description: 'Emergency fund amount',
4467
- example: 10000
4468
- },
4469
- 'filters.accounts': {
4470
- description: 'Account filter IDs',
4471
- type: 'array',
4472
- items: {
4473
- type: 'string'
4474
- }
5215
+ description: 'Lucide icon name',
5216
+ example: 'utensils'
4475
5217
  },
4476
- 'filters.assetClasses': {
4477
- description: 'Asset class filters',
5218
+ regions: {
5219
+ description: "Applicable regions ('*' = all, 'cn' = CN-only)",
5220
+ example: ['*'],
4478
5221
  type: 'array',
4479
5222
  items: {
4480
5223
  type: 'string'
4481
5224
  }
4482
- },
4483
- 'filters.dataSource': {
4484
- type: 'string',
4485
- description: 'Data source filter'
4486
- },
4487
- 'filters.symbol': {
4488
- type: 'string',
4489
- description: 'Symbol filter'
4490
- },
4491
- 'filters.tags': {
4492
- description: 'Tag filters',
5225
+ }
5226
+ },
5227
+ required: ['slug', 'scenario', 'icon', 'regions']
5228
+ } as const;
5229
+
5230
+ export const $CategoryCatalogListResponseDto = {
5231
+ type: 'object',
5232
+ properties: {
5233
+ items: {
5234
+ description: 'Category entries (region-scoped, query-filtered)',
4493
5235
  type: 'array',
4494
5236
  items: {
4495
- type: 'string'
5237
+ $ref: '#/components/schemas/CategoryCatalogEntryDto'
4496
5238
  }
4497
5239
  },
4498
- isExperimentalFeatures: {
4499
- type: 'boolean',
4500
- description: 'Enable experimental features'
4501
- },
4502
- isRestrictedView: {
4503
- type: 'boolean',
4504
- description: 'Enable restricted view mode'
4505
- },
4506
- language: {
4507
- type: 'string',
4508
- description: 'Language code',
4509
- example: 'en'
4510
- },
4511
- locale: {
4512
- type: 'string',
4513
- description: 'Locale code',
4514
- example: 'en-US'
4515
- },
4516
- projectedTotalAmount: {
4517
- type: 'number',
4518
- description: 'Projected total amount',
4519
- example: 1000000
4520
- },
4521
- retirementDate: {
4522
- type: 'string',
4523
- description: 'Retirement date in ISO 8601 format',
4524
- example: '2050-01-01'
4525
- },
4526
- savingsRate: {
5240
+ total: {
4527
5241
  type: 'number',
4528
- description: 'Savings rate percentage',
4529
- example: 0.2
5242
+ description:
5243
+ 'Total category entries for the region (before query filtering)',
5244
+ example: 30
4530
5245
  },
4531
- viewMode: {
4532
- type: 'string',
4533
- description: 'View mode',
4534
- enum: ['DEFAULT', 'ZEN']
4535
- }
4536
- }
4537
- } as const;
4538
-
4539
- export const $UpdatePropertyDto = {
4540
- type: 'object',
4541
- properties: {
4542
- value: {
5246
+ region: {
4543
5247
  type: 'string',
4544
- description: 'Property value'
5248
+ description: 'Region code',
5249
+ example: 'cn'
4545
5250
  }
4546
5251
  },
4547
- required: ['value']
5252
+ required: ['items', 'total', 'region']
4548
5253
  } as const;
4549
5254
 
4550
5255
  export const $CreateBeanEventDto = {
@@ -4710,6 +5415,14 @@ export const $OnboardingAccountDto = {
4710
5415
  description:
4711
5416
  'Platform ID to bind the account to (references Platform.id); omit for unbound',
4712
5417
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
5418
+ },
5419
+ displayName: {
5420
+ type: 'string',
5421
+ description:
5422
+ 'User-set display name override (omit/null = keep the derived name)',
5423
+ nullable: true,
5424
+ maxLength: 50,
5425
+ example: 'Salary card'
4713
5426
  }
4714
5427
  },
4715
5428
  required: ['path', 'currency']
@@ -5289,7 +6002,8 @@ export const $UpdateMapperDefaultsDto = {
5289
6002
  type: 'string',
5290
6003
  description: 'Source account for transactions (Beancount format)',
5291
6004
  example: 'Assets:CN:Alipay:Balance',
5292
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
6005
+ pattern:
6006
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5293
6007
  },
5294
6008
  currency: {
5295
6009
  type: 'string',
@@ -5303,13 +6017,15 @@ export const $UpdateMapperDefaultsDto = {
5303
6017
  type: 'string',
5304
6018
  description: 'Default expense account (optional)',
5305
6019
  example: 'Expenses:Unknown',
5306
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
6020
+ pattern:
6021
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5307
6022
  },
5308
6023
  incomeAccount: {
5309
6024
  type: 'string',
5310
6025
  description: 'Default income account (optional)',
5311
6026
  example: 'Income:Unknown',
5312
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
6027
+ pattern:
6028
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5313
6029
  },
5314
6030
  methodAccountMapping: {
5315
6031
  type: 'object',
@@ -5366,12 +6082,14 @@ export const $ProviderSyncConfigDto = {
5366
6082
  },
5367
6083
  defaultExpenseAccount: {
5368
6084
  type: 'string',
5369
- description: 'Default expense account for the second posting',
6085
+ description:
6086
+ 'Default expense account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5370
6087
  example: 'Expenses:Unknown'
5371
6088
  },
5372
6089
  defaultIncomeAccount: {
5373
6090
  type: 'string',
5374
- description: 'Default income account for the second posting',
6091
+ description:
6092
+ 'Default income account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5375
6093
  example: 'Income:Unknown'
5376
6094
  },
5377
6095
  filterPending: {
@@ -5386,12 +6104,7 @@ export const $ProviderSyncConfigDto = {
5386
6104
  example: 'acc_gocardless_001'
5387
6105
  }
5388
6106
  },
5389
- required: [
5390
- 'sourceAccount',
5391
- 'defaultCurrency',
5392
- 'defaultExpenseAccount',
5393
- 'defaultIncomeAccount'
5394
- ]
6107
+ required: ['sourceAccount', 'defaultCurrency']
5395
6108
  } as const;
5396
6109
 
5397
6110
  export const $ProviderSyncDto = {
@@ -5580,25 +6293,108 @@ export const $ExternalAccountLinkListResponseDto = {
5580
6293
  $ref: '#/components/schemas/ExternalAccountLinkResponseDto'
5581
6294
  }
5582
6295
  },
5583
- total: {
5584
- type: 'number'
6296
+ total: {
6297
+ type: 'number'
6298
+ },
6299
+ provider: {
6300
+ type: 'string',
6301
+ description: 'Filter by provider (query param)'
6302
+ }
6303
+ },
6304
+ required: ['items', 'total']
6305
+ } as const;
6306
+
6307
+ export const $ParserTelemetryReportDto = {
6308
+ type: 'object',
6309
+ properties: {}
6310
+ } as const;
6311
+
6312
+ export const $UncoveredFormatMissDto = {
6313
+ type: 'object',
6314
+ properties: {}
6315
+ } as const;
6316
+
6317
+ export const $ClientParsedDataDto = {
6318
+ type: 'object',
6319
+ properties: {
6320
+ amount: {
6321
+ type: 'number',
6322
+ description: 'Transaction amount',
6323
+ example: 35
6324
+ },
6325
+ currency: {
6326
+ type: 'string',
6327
+ description: 'Currency code',
6328
+ example: 'CNY'
6329
+ },
6330
+ date: {
6331
+ type: 'string',
6332
+ description: 'Transaction date (ISO 8601)',
6333
+ example: '2026-08-15'
6334
+ },
6335
+ payee: {
6336
+ type: 'string',
6337
+ description: 'Payee/merchant name',
6338
+ example: 'Starbucks'
6339
+ },
6340
+ narration: {
6341
+ type: 'string',
6342
+ description: 'Transaction narration'
6343
+ },
6344
+ category: {
6345
+ type: 'string',
6346
+ description: 'Category slug',
6347
+ example: 'food_restaurant'
6348
+ },
6349
+ incomeType: {
6350
+ type: 'string',
6351
+ description: 'Income type',
6352
+ example: 'Salary'
6353
+ },
6354
+ incomeSource: {
6355
+ type: 'string',
6356
+ description: 'Income source',
6357
+ example: 'Anthropic Inc.'
6358
+ },
6359
+ symbol: {
6360
+ type: 'string',
6361
+ description: 'Security symbol code (e.g., 600519, AAPL)',
6362
+ example: 'AAPL'
6363
+ },
6364
+ quantity: {
6365
+ type: 'number',
6366
+ description: 'Quantity of shares/units',
6367
+ example: 100
6368
+ },
6369
+ price: {
6370
+ type: 'number',
6371
+ description: 'Unit price per share/unit',
6372
+ example: 1900
6373
+ },
6374
+ investmentAction: {
6375
+ type: 'string',
6376
+ description: 'Investment action',
6377
+ enum: ['buy', 'sell'],
6378
+ example: 'buy'
5585
6379
  },
5586
- provider: {
6380
+ paymentSource: {
5587
6381
  type: 'string',
5588
- description: 'Filter by provider (query param)'
6382
+ description: 'Payment source: asset (default) or liability (credit card)',
6383
+ enum: ['asset', 'liability'],
6384
+ example: 'asset'
6385
+ },
6386
+ liabilityHint: {
6387
+ type: 'string',
6388
+ description: 'Liability account hint (CreditCard/Huabei/Baitiao)',
6389
+ example: 'CreditCard'
6390
+ },
6391
+ warning: {
6392
+ type: 'string',
6393
+ description:
6394
+ 'Display-only warning from the prior response; accepted but ignored.',
6395
+ example: 'Cross-currency settlement applies.'
5589
6396
  }
5590
- },
5591
- required: ['items', 'total']
5592
- } as const;
5593
-
5594
- export const $ParserTelemetryReportDto = {
5595
- type: 'object',
5596
- properties: {}
5597
- } as const;
5598
-
5599
- export const $UncoveredFormatMissDto = {
5600
- type: 'object',
5601
- properties: {}
6397
+ }
5602
6398
  } as const;
5603
6399
 
5604
6400
  export const $ProcessNlpDto = {
@@ -5606,10 +6402,17 @@ export const $ProcessNlpDto = {
5606
6402
  properties: {
5607
6403
  message: {
5608
6404
  type: 'string',
5609
- description: 'Natural language text describing a transaction (Chinese)',
5610
- example: 'yesterday Starbucks spent 35 yuan',
6405
+ description:
6406
+ 'Natural language text describing a transaction. Optional when `confirm` is true (structured confirm); otherwise required.',
6407
+ example: 'Starbucks 35',
5611
6408
  maxLength: 500
5612
6409
  },
6410
+ confirm: {
6411
+ type: 'boolean',
6412
+ description:
6413
+ 'Structured confirm signal — bypasses NL confirm-word matching when true. Send parsedData field edits alongside. The NL word-list path is the fallback.',
6414
+ example: true
6415
+ },
5613
6416
  sessionId: {
5614
6417
  type: 'string',
5615
6418
  description:
@@ -5617,17 +6420,51 @@ export const $ProcessNlpDto = {
5617
6420
  example: 'session_abc123'
5618
6421
  },
5619
6422
  parsedData: {
5620
- type: 'object',
5621
6423
  description:
5622
6424
  'Parsed data from previous NLP response for session recovery. Send back the parsedData received in confirm_payee/confirm responses.',
5623
6425
  example: {
5624
6426
  amount: 35,
5625
6427
  currency: 'CNY',
5626
6428
  payee: 'Starbucks'
5627
- }
6429
+ },
6430
+ allOf: [
6431
+ {
6432
+ $ref: '#/components/schemas/ClientParsedDataDto'
6433
+ }
6434
+ ]
6435
+ },
6436
+ selectedRuleId: {
6437
+ type: 'string',
6438
+ description:
6439
+ '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.',
6440
+ example: 'rule_abc123'
6441
+ },
6442
+ selectedAccount: {
6443
+ type: 'string',
6444
+ description:
6445
+ '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.',
6446
+ example: 'Expenses:Food:Coffee'
6447
+ },
6448
+ viewpointAccount: {
6449
+ type: 'string',
6450
+ description:
6451
+ 'Viewpoint account hint: the beancount path the user drilled into (e.g. from an account drill-down). Tie-break only — never overrides accounts resolved from the text. Must be an owned, OPEN Assets:/Liabilities: account; unresolvable hints are silently ignored.',
6452
+ example: 'Assets:CN:Bank:ICBC'
6453
+ },
6454
+ viewpointCategory: {
6455
+ type: 'string',
6456
+ description:
6457
+ "Viewpoint category hint: the ADR-0075 Group segment the user drilled into (e.g. 'Food'). Resolved to a concrete OPEN account in that group; tie-break only — never overrides a category resolved from the text.",
6458
+ example: 'Food'
6459
+ },
6460
+ viewpointFlow: {
6461
+ type: 'string',
6462
+ description:
6463
+ "Companion flow root for viewpointCategory ('income' | 'expense'), mirroring the ADR-0126 list-endpoint invariant. Derived from the session's routed intent (multi-turn) when absent; a first-turn flow-less category hint is dropped — send the flow explicitly.",
6464
+ enum: ['income', 'expense'],
6465
+ example: 'expense'
5628
6466
  }
5629
- },
5630
- required: ['message']
6467
+ }
5631
6468
  } as const;
5632
6469
 
5633
6470
  export const $NlpTransactionInfoDto = {
@@ -5939,6 +6776,24 @@ export const $NlpRuleConfirmationDataDto = {
5939
6776
  ]
5940
6777
  } as const;
5941
6778
 
6779
+ export const $NlpAccountCandidateDto = {
6780
+ type: 'object',
6781
+ properties: {
6782
+ path: {
6783
+ type: 'string',
6784
+ description: 'Canonical beancount account path (echo back on selection)',
6785
+ example: 'Expenses:Food:Dining'
6786
+ },
6787
+ name: {
6788
+ type: 'string',
6789
+ description:
6790
+ 'Localized display name (ADR-0114 read-time projection, user locale)',
6791
+ example: '餐饮'
6792
+ }
6793
+ },
6794
+ required: ['path', 'name']
6795
+ } as const;
6796
+
5942
6797
  export const $NlpAccountConfirmationDataDto = {
5943
6798
  type: 'object',
5944
6799
  properties: {
@@ -5949,14 +6804,16 @@ export const $NlpAccountConfirmationDataDto = {
5949
6804
  },
5950
6805
  suggestedAccount: {
5951
6806
  type: 'string',
5952
- description: 'Suggested replacement account',
6807
+ description:
6808
+ 'Suggested replacement account (omitted when no clear candidate)',
5953
6809
  example: 'Expenses:Food:Drinks'
5954
6810
  },
5955
6811
  similarAccounts: {
5956
- description: 'Similar accounts for user selection',
6812
+ description:
6813
+ 'Similar accounts for user selection (path + localized name, #680)',
5957
6814
  type: 'array',
5958
6815
  items: {
5959
- type: 'string'
6816
+ $ref: '#/components/schemas/NlpAccountCandidateDto'
5960
6817
  }
5961
6818
  },
5962
6819
  errorMessage: {
@@ -5971,7 +6828,6 @@ export const $NlpAccountConfirmationDataDto = {
5971
6828
  },
5972
6829
  required: [
5973
6830
  'invalidAccount',
5974
- 'suggestedAccount',
5975
6831
  'similarAccounts',
5976
6832
  'errorMessage',
5977
6833
  'transactionContext'
@@ -6144,7 +7000,8 @@ export const $NlpSuggestedAccountDto = {
6144
7000
  },
6145
7001
  confidence: {
6146
7002
  type: 'number',
6147
- description: 'Confidence score for this suggestion (0-1)',
7003
+ description:
7004
+ 'Confidence score for this suggestion (0-1). Present = predicted (confirm/confirm_rule/confirm_account); omitted = actual persisted account (created). (#586)',
6148
7005
  example: 0.9
6149
7006
  }
6150
7007
  },
@@ -6180,23 +7037,31 @@ export const $NlpDefaultAccountsDto = {
6180
7037
  properties: {
6181
7038
  asset: {
6182
7039
  type: 'string',
6183
- description: 'Default asset account',
6184
- example: 'Assets:Checking'
7040
+ description:
7041
+ 'Default OPEN asset account (MRU when multiple), or null when none/ambiguous',
7042
+ example: 'Assets:Checking',
7043
+ nullable: true
6185
7044
  },
6186
7045
  expense: {
6187
7046
  type: 'string',
6188
- description: 'Default expense account',
6189
- example: 'Expenses:Uncategorized'
7047
+ description:
7048
+ 'Default OPEN expense account (MRU when multiple), or null when none/ambiguous',
7049
+ example: 'Expenses:Food:Coffee',
7050
+ nullable: true
6190
7051
  },
6191
7052
  income: {
6192
7053
  type: 'string',
6193
- description: 'Default income account',
6194
- example: 'Income:Uncategorized'
7054
+ description:
7055
+ 'Default OPEN income account (MRU when multiple), or null when none/ambiguous',
7056
+ example: 'Income:Salary',
7057
+ nullable: true
6195
7058
  },
6196
7059
  liability: {
6197
7060
  type: 'string',
6198
- description: 'Default liability account',
6199
- example: 'Liabilities:CreditCard'
7061
+ description:
7062
+ 'Default OPEN liability account (MRU when multiple), or null when none/ambiguous',
7063
+ example: 'Liabilities:CreditCard',
7064
+ nullable: true
6200
7065
  }
6201
7066
  },
6202
7067
  required: ['asset', 'expense', 'income', 'liability']
@@ -6221,7 +7086,8 @@ export const $NlpResponseDto = {
6221
7086
  'confirm_rule',
6222
7087
  'confirm_account',
6223
7088
  'confirm_payee',
6224
- 'cancel'
7089
+ 'cancel',
7090
+ 'aborted'
6225
7091
  ]
6226
7092
  },
6227
7093
  intent: {
@@ -6235,7 +7101,7 @@ export const $NlpResponseDto = {
6235
7101
  type: 'string',
6236
7102
  description:
6237
7103
  'Asset sub-type (only present when intent is "asset"). Determines which asset-related form to render.',
6238
- enum: ['transfer', 'banking', 'investment'],
7104
+ enum: ['transfer', 'banking', 'investment', 'lend', 'lend_collect'],
6239
7105
  example: 'investment'
6240
7106
  },
6241
7107
  liabilitySubType: {
@@ -6316,91 +7182,336 @@ export const $NlpResponseDto = {
6316
7182
  }
6317
7183
  ]
6318
7184
  },
6319
- duplicateData: {
7185
+ duplicateData: {
7186
+ description:
7187
+ 'Duplicate detection data (when action is "confirm_duplicate"). Contains information about potential duplicate transaction for user confirmation.',
7188
+ allOf: [
7189
+ {
7190
+ $ref: '#/components/schemas/NlpDuplicateConfirmationDataDto'
7191
+ }
7192
+ ]
7193
+ },
7194
+ ruleData: {
7195
+ description:
7196
+ 'Rule match data (when action is "confirm_rule"). Contains information about medium-confidence rule match for user confirmation.',
7197
+ allOf: [
7198
+ {
7199
+ $ref: '#/components/schemas/NlpRuleConfirmationDataDto'
7200
+ }
7201
+ ]
7202
+ },
7203
+ accountData: {
7204
+ description:
7205
+ 'Account validation data (when action is "confirm_account"). Contains information about invalid account for user correction.',
7206
+ allOf: [
7207
+ {
7208
+ $ref: '#/components/schemas/NlpAccountConfirmationDataDto'
7209
+ }
7210
+ ]
7211
+ },
7212
+ payeeData: {
7213
+ description:
7214
+ 'Payee confirmation data (when action is "confirm_payee"). Contains information about medium/low confidence payee match for user confirmation.',
7215
+ allOf: [
7216
+ {
7217
+ $ref: '#/components/schemas/NlpPayeeConfirmationDataDto'
7218
+ }
7219
+ ]
7220
+ },
7221
+ confidence: {
7222
+ type: 'number',
7223
+ description: 'Overall confidence score (0-1)',
7224
+ example: 0.85
7225
+ },
7226
+ confidenceThreshold: {
7227
+ type: 'number',
7228
+ description:
7229
+ 'Confidence threshold for automatic creation (default: 0.75). When confidence < threshold, action will be "confirm" requiring user verification.',
7230
+ example: 0.75
7231
+ },
7232
+ recurringMatch: {
7233
+ description:
7234
+ 'Recurring transaction match info (when action is "created"). Contains match details when transaction matches a pending expected transaction.',
7235
+ allOf: [
7236
+ {
7237
+ $ref: '#/components/schemas/RecurringMatchInfoDto'
7238
+ }
7239
+ ]
7240
+ },
7241
+ recurringSuggestion: {
7242
+ description:
7243
+ 'Recurring rule creation suggestion (when action is "created"). Contains suggestion to create a recurring rule based on detected patterns. Only present when no existing rule matched and similar historical transactions were found.',
7244
+ allOf: [
7245
+ {
7246
+ $ref: '#/components/schemas/RecurringSuggestionDto'
7247
+ }
7248
+ ]
7249
+ },
7250
+ suggestedAccounts: {
7251
+ description:
7252
+ '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.',
7253
+ allOf: [
7254
+ {
7255
+ $ref: '#/components/schemas/NlpSuggestedAccountsDto'
7256
+ }
7257
+ ]
7258
+ },
7259
+ defaultAccounts: {
7260
+ description:
7261
+ 'Default fallback accounts for the user/region (#586). v1 returns universal constants; per-user personalization is planned.',
7262
+ allOf: [
7263
+ {
7264
+ $ref: '#/components/schemas/NlpDefaultAccountsDto'
7265
+ }
7266
+ ]
7267
+ }
7268
+ },
7269
+ required: ['status', 'action']
7270
+ } as const;
7271
+
7272
+ export const $PlatformListItemDto = {
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'
7282
+ },
7283
+ url: {
7284
+ type: 'string',
7285
+ description: 'Platform URL'
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
+ canonical: {
7301
+ type: 'string',
7302
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7303
+ },
7304
+ suggestedSegment: {
7305
+ type: 'string',
7306
+ description:
7307
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7308
+ },
7309
+ logoUrl: {
7310
+ type: 'string',
7311
+ description: 'Logo URL',
7312
+ nullable: true
7313
+ },
7314
+ countryCode: {
7315
+ type: 'string',
7316
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7317
+ example: 'CN',
7318
+ nullable: true
7319
+ },
7320
+ category: {
7321
+ type: 'string',
7322
+ description:
7323
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7324
+ nullable: true,
7325
+ example: 'DigitalWallet'
7326
+ },
7327
+ isBound: {
7328
+ type: 'boolean',
7329
+ description: 'Whether user has accounts using this platform'
7330
+ }
7331
+ },
7332
+ required: [
7333
+ 'id',
7334
+ 'name',
7335
+ 'url',
7336
+ 'type',
7337
+ 'canonical',
7338
+ 'suggestedSegment',
7339
+ 'logoUrl',
7340
+ 'countryCode',
7341
+ 'category',
7342
+ 'isBound'
7343
+ ]
7344
+ } as const;
7345
+
7346
+ export const $PlatformMatchResultDto = {
7347
+ type: 'object',
7348
+ properties: {
7349
+ id: {
7350
+ type: 'string',
7351
+ description: 'Global platform ID'
7352
+ },
7353
+ name: {
7354
+ type: 'string',
7355
+ description: 'Platform name (e.g., "ICBC")'
7356
+ },
7357
+ canonical: {
7358
+ type: 'string',
7359
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7360
+ },
7361
+ type: {
7362
+ type: 'string',
7363
+ description: 'Platform type',
7364
+ enum: [
7365
+ 'BANK',
7366
+ 'BROKERAGE',
7367
+ 'CRYPTO_EXCHANGE',
7368
+ 'PAYMENT',
7369
+ 'INVESTMENT',
7370
+ 'INSURANCE',
7371
+ 'OTHER'
7372
+ ]
7373
+ },
7374
+ suggestedSegment: {
7375
+ type: 'string',
6320
7376
  description:
6321
- 'Duplicate detection data (when action is "confirm_duplicate"). Contains information about potential duplicate transaction for user confirmation.',
6322
- allOf: [
6323
- {
6324
- $ref: '#/components/schemas/NlpDuplicateConfirmationDataDto'
6325
- }
6326
- ]
7377
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
6327
7378
  },
6328
- ruleData: {
6329
- description:
6330
- 'Rule match data (when action is "confirm_rule"). Contains information about medium-confidence rule match for user confirmation.',
6331
- allOf: [
6332
- {
6333
- $ref: '#/components/schemas/NlpRuleConfirmationDataDto'
6334
- }
6335
- ]
7379
+ logoUrl: {
7380
+ type: 'string',
7381
+ description: 'Logo URL',
7382
+ nullable: true
6336
7383
  },
6337
- accountData: {
7384
+ countryCode: {
7385
+ type: 'string',
7386
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7387
+ example: 'CN',
7388
+ nullable: true
7389
+ },
7390
+ category: {
7391
+ type: 'string',
6338
7392
  description:
6339
- 'Account validation data (when action is "confirm_account"). Contains information about invalid account for user correction.',
6340
- allOf: [
6341
- {
6342
- $ref: '#/components/schemas/NlpAccountConfirmationDataDto'
6343
- }
6344
- ]
7393
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7394
+ nullable: true,
7395
+ example: 'DigitalWallet'
6345
7396
  },
6346
- payeeData: {
7397
+ matchType: {
7398
+ type: 'string',
7399
+ description: "How this row matched: 'exact' > 'prefix' > 'substring'",
7400
+ enum: ['exact', 'prefix', 'substring']
7401
+ }
7402
+ },
7403
+ required: [
7404
+ 'id',
7405
+ 'name',
7406
+ 'canonical',
7407
+ 'type',
7408
+ 'suggestedSegment',
7409
+ 'logoUrl',
7410
+ 'countryCode',
7411
+ 'category',
7412
+ 'matchType'
7413
+ ]
7414
+ } as const;
7415
+
7416
+ export const $PlatformMatchResponseDto = {
7417
+ type: 'object',
7418
+ properties: {
7419
+ platforms: {
7420
+ description: 'Ranked matches, best tier first (at most 10 rows)',
7421
+ type: 'array',
7422
+ items: {
7423
+ $ref: '#/components/schemas/PlatformMatchResultDto'
7424
+ }
7425
+ },
7426
+ matchType: {
7427
+ type: 'string',
6347
7428
  description:
6348
- 'Payee confirmation data (when action is "confirm_payee"). Contains information about medium/low confidence payee match for user confirmation.',
6349
- allOf: [
6350
- {
6351
- $ref: '#/components/schemas/NlpPayeeConfirmationDataDto'
6352
- }
6353
- ]
7429
+ "Overall match quality — top row's tier, or 'none' when no hits",
7430
+ enum: ['none', 'exact', 'prefix', 'substring']
6354
7431
  },
6355
- confidence: {
7432
+ total: {
6356
7433
  type: 'number',
6357
- description: 'Overall confidence score (0-1)',
6358
- example: 0.85
7434
+ description: 'Total matches before LIMIT (truncation transparency)'
6359
7435
  },
6360
- confidenceThreshold: {
6361
- type: 'number',
6362
- description:
6363
- 'Confidence threshold for automatic creation (default: 0.75). When confidence < threshold, action will be "confirm" requiring user verification.',
6364
- example: 0.75
7436
+ hasMore: {
7437
+ type: 'boolean',
7438
+ description: 'true when total > platforms.length (more matches exist)'
7439
+ }
7440
+ },
7441
+ required: ['platforms', 'matchType', 'total', 'hasMore']
7442
+ } as const;
7443
+
7444
+ export const $PlatformStandardsPlatformDto = {
7445
+ type: 'object',
7446
+ properties: {
7447
+ id: {
7448
+ type: 'string',
7449
+ description: 'Global platform ID'
6365
7450
  },
6366
- recurringMatch: {
7451
+ name: {
7452
+ type: 'string',
7453
+ description: 'Platform name (e.g., "ICBC")'
7454
+ },
7455
+ canonical: {
7456
+ type: 'string',
7457
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7458
+ },
7459
+ suggestedSegment: {
7460
+ type: 'string',
6367
7461
  description:
6368
- 'Recurring transaction match info (when action is "created"). Contains match details when transaction matches a pending expected transaction.',
6369
- allOf: [
6370
- {
6371
- $ref: '#/components/schemas/RecurringMatchInfoDto'
6372
- }
7462
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7463
+ },
7464
+ type: {
7465
+ type: 'string',
7466
+ description: 'Platform type',
7467
+ enum: [
7468
+ 'BANK',
7469
+ 'BROKERAGE',
7470
+ 'CRYPTO_EXCHANGE',
7471
+ 'PAYMENT',
7472
+ 'INVESTMENT',
7473
+ 'INSURANCE',
7474
+ 'OTHER'
6373
7475
  ]
6374
7476
  },
6375
- recurringSuggestion: {
7477
+ category: {
7478
+ type: 'string',
6376
7479
  description:
6377
- 'Recurring rule creation suggestion (when action is "created"). Contains suggestion to create a recurring rule based on detected patterns. Only present when no existing rule matched and similar historical transactions were found.',
7480
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank) resolved against the final region. null = no region-aware suggestion; fall back to type.',
7481
+ nullable: true,
7482
+ example: 'Bank'
7483
+ }
7484
+ },
7485
+ required: ['id', 'name', 'canonical', 'suggestedSegment', 'type', 'category']
7486
+ } as const;
7487
+
7488
+ export const $PlatformStandardsResponseDto = {
7489
+ type: 'object',
7490
+ properties: {
7491
+ platform: {
7492
+ description: 'The selected platform (institution lock source)',
6378
7493
  allOf: [
6379
7494
  {
6380
- $ref: '#/components/schemas/RecurringSuggestionDto'
7495
+ $ref: '#/components/schemas/PlatformStandardsPlatformDto'
6381
7496
  }
6382
7497
  ]
6383
7498
  },
6384
- suggestedAccounts: {
7499
+ region: {
7500
+ type: 'string',
6385
7501
  description:
6386
- 'Suggested accounts for this transaction. Contains recommended source and destination accounts based on the detected intent and rules.',
6387
- allOf: [
6388
- {
6389
- $ref: '#/components/schemas/NlpSuggestedAccountsDto'
6390
- }
6391
- ]
7502
+ "Resolved template region (ISO 3166-1 alpha-2, UPPERCASE): the platform's own countryCode when set, else the region query param. For regions without a regional template file the template list falls back to the universal-only catalog while region still echoes the code.",
7503
+ example: 'CN'
6392
7504
  },
6393
- defaultAccounts: {
7505
+ templates: {
6394
7506
  description:
6395
- 'Default accounts for the user/region. These are fallback accounts used when no specific suggestion is available.',
6396
- allOf: [
6397
- {
6398
- $ref: '#/components/schemas/NlpDefaultAccountsDto'
6399
- }
6400
- ]
7507
+ 'Candidate account-standard templates of the resolved region (groupable by productCategory client-side)',
7508
+ type: 'array',
7509
+ items: {
7510
+ $ref: '#/components/schemas/AccountStandardResponseDto'
7511
+ }
6401
7512
  }
6402
7513
  },
6403
- required: ['status', 'action']
7514
+ required: ['platform', 'region', 'templates']
6404
7515
  } as const;
6405
7516
 
6406
7517
  export const $CreatePlatformDto = {
@@ -6504,7 +7615,8 @@ export const $UpdatePlatformDto = {
6504
7615
  },
6505
7616
  isActive: {
6506
7617
  type: 'boolean',
6507
- description: 'Whether the platform is active'
7618
+ description: 'Whether the platform is active',
7619
+ default: true
6508
7620
  }
6509
7621
  }
6510
7622
  } as const;
@@ -6667,7 +7779,8 @@ export const $AccountItemDto = {
6667
7779
  },
6668
7780
  displayName: {
6669
7781
  type: 'string',
6670
- description: 'Display name (last part of account path)',
7782
+ description:
7783
+ 'Display name: user-set name if provided (#762), else last part of account path',
6671
7784
  example: 'Savings'
6672
7785
  },
6673
7786
  balance: {
@@ -6703,7 +7816,8 @@ export const $PlatformGroupDto = {
6703
7816
  example: 'CMB Bank'
6704
7817
  },
6705
7818
  accounts: {
6706
- description: 'Accounts within this platform',
7819
+ description:
7820
+ 'Accounts within this platform (Assets and Liabilities rows, #696)',
6707
7821
  type: 'array',
6708
7822
  items: {
6709
7823
  $ref: '#/components/schemas/AccountItemDto'
@@ -6711,7 +7825,8 @@ export const $PlatformGroupDto = {
6711
7825
  },
6712
7826
  totalBalance: {
6713
7827
  type: 'string',
6714
- description: 'FX-converted total balance in base currency',
7828
+ description:
7829
+ 'FX-converted total balance in base currency (nets Assets + Liabilities rows; can be negative)',
6715
7830
  example: '100000.00'
6716
7831
  },
6717
7832
  balanceByCurrency: {
@@ -6730,7 +7845,7 @@ export const $PlatformGroupDto = {
6730
7845
  sharePct: {
6731
7846
  type: 'number',
6732
7847
  description:
6733
- 'Share of the grand converted total (0-100); 0 when grand total is 0',
7848
+ 'Share of the converted asset-side grand total (0-100); liability balances are excluded from the basis; 0 when grand total is 0 (#696)',
6734
7849
  example: 42.5
6735
7850
  }
6736
7851
  },
@@ -6778,7 +7893,8 @@ export const $AccountsSummaryDto = {
6778
7893
  properties: {
6779
7894
  totalAccounts: {
6780
7895
  type: 'number',
6781
- description: 'Total number of accounts'
7896
+ description:
7897
+ 'Total number of accounts (balance sheet: Assets + Liabilities, #696)'
6782
7898
  },
6783
7899
  totalPlatforms: {
6784
7900
  type: 'number',
@@ -6836,7 +7952,8 @@ export const $AccountItemWithAssetClassDto = {
6836
7952
  },
6837
7953
  displayName: {
6838
7954
  type: 'string',
6839
- description: 'Display name (last part of account path)',
7955
+ description:
7956
+ 'Display name: user-set name if provided (#762), else last part of account path',
6840
7957
  example: 'Savings'
6841
7958
  },
6842
7959
  balance: {
@@ -7322,7 +8439,7 @@ export const $MonetaryDto = {
7322
8439
  example: 'USD'
7323
8440
  },
7324
8441
  baseCcyEquivalent: {
7325
- type: 'object',
8442
+ type: 'string',
7326
8443
  description: 'Converted to user base currency (Decimal string)',
7327
8444
  example: '21600',
7328
8445
  nullable: true
@@ -7398,13 +8515,13 @@ export const $HoldingPnlRowDto = {
7398
8515
  example: 'Assets:US:Broker:AAPL'
7399
8516
  },
7400
8517
  accountCcy: {
7401
- type: 'object',
8518
+ type: 'string',
7402
8519
  description: 'Account settlement currency (ISO 4217), from cost currency',
7403
8520
  nullable: true,
7404
8521
  example: 'USD'
7405
8522
  },
7406
8523
  brokerType: {
7407
- type: 'object',
8524
+ type: 'string',
7408
8525
  description: 'Broker type derived from Platform.type',
7409
8526
  nullable: true,
7410
8527
  example: 'broker'
@@ -7425,7 +8542,7 @@ export const $HoldingPnlRowDto = {
7425
8542
  example: 'EQUITY'
7426
8543
  },
7427
8544
  assetSubClass: {
7428
- type: 'object',
8545
+ type: 'string',
7429
8546
  nullable: true,
7430
8547
  example: 'STOCK'
7431
8548
  },
@@ -7472,14 +8589,14 @@ export const $HoldingPnlRowDto = {
7472
8589
  ]
7473
8590
  },
7474
8591
  unrealizedPnlBase: {
7475
- type: 'object',
8592
+ type: 'string',
7476
8593
  description:
7477
8594
  'Unrealized P&L in base currency (Decimal string); null when any FX/price missing',
7478
8595
  nullable: true,
7479
8596
  example: '6000'
7480
8597
  },
7481
8598
  unrealizedPnlPct: {
7482
- type: 'object',
8599
+ type: 'string',
7483
8600
  description: 'Unrealized P&L % (Decimal string)',
7484
8601
  nullable: true,
7485
8602
  example: '25'
@@ -7503,7 +8620,7 @@ export const $HoldingPnlRowDto = {
7503
8620
  ]
7504
8621
  },
7505
8622
  pctOfInvestedAssets: {
7506
- type: 'object',
8623
+ type: 'string',
7507
8624
  description:
7508
8625
  'Share of invested assets % (Decimal string); only for invested chartTokens',
7509
8626
  nullable: true,
@@ -7548,15 +8665,15 @@ export const $HoldingPnlWarningDto = {
7548
8665
  ]
7549
8666
  },
7550
8667
  symbol: {
7551
- type: 'object',
8668
+ type: 'string',
7552
8669
  nullable: true
7553
8670
  },
7554
8671
  accountId: {
7555
- type: 'object',
8672
+ type: 'string',
7556
8673
  nullable: true
7557
8674
  },
7558
8675
  currency: {
7559
- type: 'object',
8676
+ type: 'string',
7560
8677
  nullable: true
7561
8678
  }
7562
8679
  },
@@ -7597,292 +8714,378 @@ export const $HoldingPnlResponseDto = {
7597
8714
  required: ['asOfDate', 'baseCurrency', 'method', 'rows', 'warnings']
7598
8715
  } as const;
7599
8716
 
7600
- export const $CurrencyBalanceDto = {
8717
+ export const $AnonymousLoginDto = {
7601
8718
  type: 'object',
7602
8719
  properties: {
7603
- currency: {
8720
+ accessToken: {
7604
8721
  type: 'string',
7605
- description: 'ISO 4217 currency code',
7606
- example: 'CNY'
7607
- },
7608
- balance: {
8722
+ description: 'Access token for anonymous login'
8723
+ }
8724
+ },
8725
+ required: ['accessToken']
8726
+ } as const;
8727
+
8728
+ export const $AnonymousLoginResponseDto = {
8729
+ type: 'object',
8730
+ properties: {
8731
+ authToken: {
7609
8732
  type: 'string',
7610
- description: 'Balance amount',
7611
- example: '500000.00'
8733
+ description: 'JWT auth token',
8734
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
7612
8735
  }
7613
8736
  },
7614
- required: ['currency', 'balance']
8737
+ required: ['authToken']
7615
8738
  } as const;
7616
8739
 
7617
- export const $TimeSeriesPointDto = {
8740
+ export const $ParserContributionMetaDto = {
7618
8741
  type: 'object',
7619
8742
  properties: {
7620
- date: {
8743
+ institution: {
7621
8744
  type: 'string',
7622
- description: 'Date in YYYY-MM-DD format',
7623
- example: '2024-06-15'
8745
+ description: 'Institution slug (lowercase kebab-case)',
8746
+ pattern: '^[a-z0-9]+(-[a-z0-9]+)*$',
8747
+ example: 'icbc'
7624
8748
  },
7625
- value: {
8749
+ region: {
7626
8750
  type: 'string',
7627
- description: 'Value at this date (in base currency)',
7628
- example: '500000.00'
8751
+ enum: [
8752
+ 'cn',
8753
+ 'us',
8754
+ 'de',
8755
+ 'fr',
8756
+ 'gb',
8757
+ 'hk',
8758
+ 'jp',
8759
+ 'sg',
8760
+ 'au',
8761
+ 'ca',
8762
+ 'other'
8763
+ ]
7629
8764
  },
7630
- change: {
7631
- type: 'object',
7632
- description: 'Change from previous point',
7633
- example: '5000.00'
8765
+ accountType: {
8766
+ type: 'string',
8767
+ enum: ['checking', 'savings', 'credit', 'debit', 'investment']
7634
8768
  },
7635
- assets: {
8769
+ format: {
7636
8770
  type: 'string',
7637
- description: 'Total assets at this date (in base currency)',
7638
- example: '494338.00'
8771
+ enum: ['csv', 'xlsx', 'pdf', 'ofx', 'qif']
7639
8772
  },
7640
- liabilities: {
8773
+ institutionDisplayName: {
7641
8774
  type: 'string',
7642
- description: 'Total liabilities at this date (in base currency)',
7643
- example: '310098.00'
8775
+ example: '中国工商银行'
7644
8776
  },
7645
- byCurrency: {
7646
- description: 'Multi-currency breakdown for this point',
8777
+ encoding: {
8778
+ type: 'string',
8779
+ example: 'utf-8'
8780
+ },
8781
+ delimiter: {
8782
+ type: 'string',
8783
+ description: 'CSV delimiter character: ",", ";", "\\t" or "|"'
8784
+ },
8785
+ headerRows: {
8786
+ type: 'number',
8787
+ default: 1,
8788
+ description: 'Header row count; the client omits the field when it is 1'
8789
+ },
8790
+ notes: {
8791
+ type: 'string',
8792
+ maxLength: 2000
8793
+ }
8794
+ },
8795
+ required: ['institution', 'region', 'accountType', 'format']
8796
+ } as const;
8797
+
8798
+ export const $ParserContributionSamplesDto = {
8799
+ type: 'object',
8800
+ properties: {
8801
+ rows: {
8802
+ description:
8803
+ 'Client-sanitized sample rows (key = column name, value = cell)',
7647
8804
  type: 'array',
7648
8805
  items: {
7649
- $ref: '#/components/schemas/CurrencyBalanceDto'
8806
+ type: 'object'
7650
8807
  }
8808
+ },
8809
+ rawHeaders: {
8810
+ type: 'array',
8811
+ items: {
8812
+ type: 'string'
8813
+ }
8814
+ }
8815
+ },
8816
+ required: ['rows']
8817
+ } as const;
8818
+
8819
+ export const $FieldHintDto = {
8820
+ type: 'object',
8821
+ properties: {
8822
+ columnName: {
8823
+ type: 'string',
8824
+ example: '交易日期'
8825
+ },
8826
+ format: {
8827
+ type: 'string',
8828
+ description: 'Date format, e.g. yyyy-MM-dd HH:mm',
8829
+ example: 'yyyy-MM-dd'
8830
+ },
8831
+ signConvention: {
8832
+ type: 'string',
8833
+ enum: ['negative-expense', 'positive-expense', 'separate-columns']
8834
+ },
8835
+ creditColumn: {
8836
+ type: 'string'
8837
+ },
8838
+ debitColumn: {
8839
+ type: 'string'
8840
+ }
8841
+ },
8842
+ required: ['columnName']
8843
+ } as const;
8844
+
8845
+ export const $ParserContributionFieldHintsDto = {
8846
+ type: 'object',
8847
+ properties: {
8848
+ date: {
8849
+ $ref: '#/components/schemas/FieldHintDto'
8850
+ },
8851
+ amount: {
8852
+ $ref: '#/components/schemas/FieldHintDto'
8853
+ },
8854
+ description: {
8855
+ $ref: '#/components/schemas/FieldHintDto'
8856
+ },
8857
+ balance: {
8858
+ $ref: '#/components/schemas/FieldHintDto'
8859
+ },
8860
+ payee: {
8861
+ $ref: '#/components/schemas/FieldHintDto'
8862
+ },
8863
+ reference: {
8864
+ $ref: '#/components/schemas/FieldHintDto'
8865
+ },
8866
+ category: {
8867
+ $ref: '#/components/schemas/FieldHintDto'
7651
8868
  }
7652
8869
  },
7653
- required: ['date', 'value']
8870
+ required: ['date', 'amount']
7654
8871
  } as const;
7655
8872
 
7656
- export const $TrendSummaryDto = {
8873
+ export const $ExpectedTransactionDto = {
7657
8874
  type: 'object',
7658
8875
  properties: {
7659
- startValue: {
8876
+ date: {
7660
8877
  type: 'string',
7661
- description: 'Value at start of period',
7662
- example: '450000.00'
8878
+ example: '2026-08-01'
7663
8879
  },
7664
- endValue: {
7665
- type: 'string',
7666
- description: 'Value at end of period',
7667
- example: '500000.00'
8880
+ amount: {
8881
+ type: 'number',
8882
+ example: -45.5
7668
8883
  },
7669
- totalChange: {
8884
+ description: {
7670
8885
  type: 'string',
7671
- description: 'Total change over period',
7672
- example: '50000.00'
8886
+ example: '星巴克-***店'
7673
8887
  },
7674
- totalChangePercentage: {
7675
- type: 'string',
7676
- description: 'Total change percentage',
7677
- example: '+11.11%'
8888
+ payee: {
8889
+ type: 'string'
8890
+ },
8891
+ category: {
8892
+ type: 'string'
7678
8893
  }
7679
8894
  },
7680
- required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
8895
+ required: ['date', 'amount', 'description']
7681
8896
  } as const;
7682
8897
 
7683
- export const $MultiCurrencyPointDto = {
8898
+ export const $ParserContributionExamplesDto = {
7684
8899
  type: 'object',
7685
8900
  properties: {
7686
- date: {
7687
- type: 'string',
7688
- description: 'Date in YYYY-MM-DD format',
7689
- example: '2024-06-15'
7690
- },
7691
- byCurrency: {
7692
- description: 'Balances by currency',
8901
+ expectedTransactions: {
7693
8902
  type: 'array',
7694
8903
  items: {
7695
- $ref: '#/components/schemas/CurrencyBalanceDto'
8904
+ $ref: '#/components/schemas/ExpectedTransactionDto'
7696
8905
  }
7697
8906
  }
7698
8907
  },
7699
- required: ['date', 'byCurrency']
8908
+ required: ['expectedTransactions']
7700
8909
  } as const;
7701
8910
 
7702
- export const $PortfolioTrendsResponseDto = {
8911
+ export const $ParserContributionRequestDto = {
7703
8912
  type: 'object',
7704
8913
  properties: {
7705
- series: {
7706
- description: 'Time series data points',
7707
- type: 'array',
7708
- items: {
7709
- $ref: '#/components/schemas/TimeSeriesPointDto'
7710
- }
8914
+ meta: {
8915
+ $ref: '#/components/schemas/ParserContributionMetaDto'
7711
8916
  },
7712
- summary: {
7713
- description: 'Period summary',
8917
+ samples: {
8918
+ $ref: '#/components/schemas/ParserContributionSamplesDto'
8919
+ },
8920
+ fieldHints: {
8921
+ $ref: '#/components/schemas/ParserContributionFieldHintsDto'
8922
+ },
8923
+ examples: {
8924
+ description: 'Omitted entirely by the client when empty',
7714
8925
  allOf: [
7715
8926
  {
7716
- $ref: '#/components/schemas/TrendSummaryDto'
8927
+ $ref: '#/components/schemas/ParserContributionExamplesDto'
7717
8928
  }
7718
8929
  ]
7719
- },
7720
- period: {
7721
- type: 'string',
7722
- description: 'Period requested',
7723
- example: '6m'
7724
- },
7725
- granularity: {
7726
- type: 'string',
7727
- description: 'Data granularity',
7728
- example: 'month'
7729
- },
7730
- currency: {
8930
+ }
8931
+ },
8932
+ required: ['meta', 'samples', 'fieldHints']
8933
+ } as const;
8934
+
8935
+ export const $ParserContributionRelayResponseDto = {
8936
+ type: 'object',
8937
+ properties: {
8938
+ issueUrl: {
7731
8939
  type: 'string',
7732
- description: 'Base currency for converted values',
7733
- example: 'CNY'
7734
- },
7735
- byCurrency: {
7736
- description:
7737
- 'Multi-currency time series (each point has currency breakdown)',
7738
- type: 'array',
7739
- items: {
7740
- $ref: '#/components/schemas/MultiCurrencyPointDto'
7741
- }
8940
+ example: 'https://github.com/fire-zu/firela-vlt/issues/42'
7742
8941
  },
7743
- warnings: {
7744
- description: 'Exchange rate warnings',
7745
- type: 'array',
7746
- items: {
7747
- $ref: '#/components/schemas/ExchangeRateWarningDto'
7748
- }
8942
+ issueNumber: {
8943
+ type: 'number',
8944
+ example: 42
7749
8945
  }
7750
8946
  },
7751
- required: ['series', 'summary', 'period', 'granularity', 'currency']
8947
+ required: ['issueUrl', 'issueNumber']
7752
8948
  } as const;
7753
8949
 
7754
- export const $CashFlowPointDto = {
8950
+ export const $SymbolSearchResultDto = {
7755
8951
  type: 'object',
7756
8952
  properties: {
7757
- month: {
8953
+ symbol: {
7758
8954
  type: 'string',
7759
- description: 'Month key (YYYY-MM)',
7760
- example: '2024-03'
8955
+ example: 'AAPL'
7761
8956
  },
7762
- income: {
8957
+ name: {
7763
8958
  type: 'string',
7764
- description: 'Income in base currency (absolute, converted)',
7765
- example: '10000.00'
8959
+ example: 'Apple Inc.',
8960
+ nullable: true
7766
8961
  },
7767
- expense: {
8962
+ exchange: {
7768
8963
  type: 'string',
7769
- description: 'Expense in base currency (absolute, converted)',
7770
- example: '5000.00'
8964
+ example: 'US',
8965
+ nullable: true
7771
8966
  },
7772
- netSavings: {
8967
+ assetType: {
7773
8968
  type: 'string',
7774
- description: 'netSavings = income − expense (savings positive)',
7775
- example: '5000.00'
8969
+ description: 'OpenBB asset_type (e.g. stock, etf)',
8970
+ example: 'stock',
8971
+ nullable: true
8972
+ },
8973
+ assetClass: {
8974
+ type: 'string',
8975
+ description: 'IGN asset class (region.types.ts ASSET_CLASSES)',
8976
+ example: 'EQUITY',
8977
+ nullable: true
8978
+ },
8979
+ assetSubClass: {
8980
+ type: 'string',
8981
+ description: 'IGN asset sub-class (region.types.ts ASSET_SUB_CLASSES)',
8982
+ example: 'STOCK',
8983
+ nullable: true
8984
+ },
8985
+ currency: {
8986
+ type: 'string',
8987
+ description: 'Trading currency (extra_data or inferred from exchange)',
8988
+ example: 'USD',
8989
+ nullable: true
7776
8990
  }
7777
8991
  },
7778
- required: ['month', 'income', 'expense', 'netSavings']
8992
+ required: ['symbol']
7779
8993
  } as const;
7780
8994
 
7781
- export const $CashFlowTrendSummaryDto = {
8995
+ export const $SymbolQuoteDto = {
7782
8996
  type: 'object',
7783
8997
  properties: {
7784
- totalIncome: {
8998
+ symbol: {
7785
8999
  type: 'string',
7786
- description: 'Total income across the period',
7787
- example: '60000.00'
9000
+ example: 'AAPL'
7788
9001
  },
7789
- totalExpense: {
9002
+ name: {
7790
9003
  type: 'string',
7791
- description: 'Total expense across the period',
7792
- example: '30000.00'
9004
+ example: 'Apple Inc.',
9005
+ nullable: true
7793
9006
  },
7794
- totalNetSavings: {
9007
+ exchange: {
7795
9008
  type: 'string',
7796
- description: 'income − expense across the period',
7797
- example: '30000.00'
9009
+ example: 'US',
9010
+ nullable: true
7798
9011
  },
7799
- averageMonthlyNetSavings: {
9012
+ assetType: {
7800
9013
  type: 'string',
9014
+ description: 'OpenBB asset_type',
9015
+ example: 'stock',
9016
+ nullable: true
9017
+ },
9018
+ assetClass: {
9019
+ type: 'string',
9020
+ description: 'IGN asset class',
9021
+ example: 'EQUITY',
9022
+ nullable: true
9023
+ },
9024
+ assetSubClass: {
9025
+ type: 'string',
9026
+ description: 'IGN asset sub-class',
9027
+ example: 'STOCK',
9028
+ nullable: true
9029
+ },
9030
+ currency: {
9031
+ type: 'string',
9032
+ description: 'Trading currency (extra_data or inferred from exchange)',
9033
+ example: 'USD',
9034
+ nullable: true
9035
+ },
9036
+ price: {
9037
+ type: 'string',
9038
+ description: 'Latest price (Decimal string)',
9039
+ example: '189.84',
9040
+ nullable: true
9041
+ },
9042
+ priceDate: {
9043
+ type: 'string',
9044
+ description: 'Date the price was observed (ISO yyyy-MM-dd)',
9045
+ example: '2026-08-05',
9046
+ nullable: true
9047
+ },
9048
+ changePercent: {
9049
+ type: 'number',
7801
9050
  description:
7802
- 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
7803
- example: '5000.00'
7804
- }
7805
- },
7806
- required: [
7807
- 'totalIncome',
7808
- 'totalExpense',
7809
- 'totalNetSavings',
7810
- 'averageMonthlyNetSavings'
7811
- ]
7812
- } as const;
7813
-
7814
- export const $CashFlowTrendsResponseDto = {
7815
- type: 'object',
7816
- properties: {
7817
- series: {
7818
- description:
7819
- 'Monthly cash-flow series (fixed N-month window, zero-filled)',
7820
- type: 'array',
7821
- items: {
7822
- $ref: '#/components/schemas/CashFlowPointDto'
7823
- }
9051
+ '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.',
9052
+ example: 1.7,
9053
+ nullable: true
7824
9054
  },
7825
- summary: {
7826
- description: 'Period totals',
7827
- allOf: [
7828
- {
7829
- $ref: '#/components/schemas/CashFlowTrendSummaryDto'
7830
- }
7831
- ]
9055
+ prevClose: {
9056
+ type: 'string',
9057
+ description: 'Previous close (Decimal string)',
9058
+ nullable: true
7832
9059
  },
7833
- period: {
9060
+ open: {
7834
9061
  type: 'string',
7835
- description: 'Period requested',
7836
- example: '6m'
9062
+ description: 'Day open (Decimal string)',
9063
+ nullable: true
7837
9064
  },
7838
- granularity: {
9065
+ high: {
7839
9066
  type: 'string',
7840
- description: 'Data granularity (v1 returns month buckets)',
7841
- example: 'month'
9067
+ description: 'Day high (Decimal string)',
9068
+ nullable: true
7842
9069
  },
7843
- currency: {
9070
+ low: {
7844
9071
  type: 'string',
7845
- description: 'Base currency for converted values',
7846
- example: 'CNY'
9072
+ description: 'Day low (Decimal string)',
9073
+ nullable: true
7847
9074
  },
7848
- warnings: {
7849
- description: 'Exchange rate warnings (e.g. missing rate for a currency)',
7850
- type: 'array',
7851
- items: {
7852
- $ref: '#/components/schemas/ExchangeRateWarningDto'
7853
- }
7854
- }
7855
- },
7856
- required: ['series', 'summary', 'period', 'granularity', 'currency']
7857
- } as const;
7858
-
7859
- export const $GenerateSnapshotBody = {
7860
- type: 'object',
7861
- properties: {}
7862
- } as const;
7863
-
7864
- export const $GenerateSnapshotResponse = {
7865
- type: 'object',
7866
- properties: {}
7867
- } as const;
7868
-
7869
- export const $BackfillSnapshotsBody = {
7870
- type: 'object',
7871
- properties: {}
7872
- } as const;
7873
-
7874
- export const $BackfillSnapshotsResponse = {
7875
- type: 'object',
7876
- properties: {}
7877
- } as const;
7878
-
7879
- export const $AnonymousLoginDto = {
7880
- type: 'object',
7881
- properties: {
7882
- accessToken: {
9075
+ volume: {
7883
9076
  type: 'string',
7884
- description: 'Access token for anonymous login'
9077
+ description: 'Day volume (Decimal string)',
9078
+ nullable: true
9079
+ },
9080
+ yearHigh: {
9081
+ type: 'string',
9082
+ description: '52-week high (Decimal string)',
9083
+ nullable: true
9084
+ },
9085
+ yearLow: {
9086
+ type: 'string',
9087
+ description: '52-week low (Decimal string)',
9088
+ nullable: true
7885
9089
  }
7886
- },
7887
- required: ['accessToken']
9090
+ }
7888
9091
  } as const;