@firela/api-types 0.0.0-canary.688167dd → 0.0.0-canary.69a6df79

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.
@@ -124,6 +124,8 @@ export const $AccountResponseDto = {
124
124
  'STUDENT_LOAN',
125
125
  'CREDIT_CARD',
126
126
  'PERSONAL_LOAN',
127
+ 'ACCOUNTS_PAYABLE',
128
+ 'TAX_PAYABLE',
127
129
  'OTHER'
128
130
  ],
129
131
  nullable: true,
@@ -395,9 +397,47 @@ export const $AccountStandardResponseDto = {
395
397
  type: 'string',
396
398
  description: 'Icon identifier for UI display',
397
399
  example: 'bank-icbc'
400
+ },
401
+ productCategory: {
402
+ type: 'string',
403
+ description:
404
+ 'Onboarding product category (coarse grouping derived from assetSubClass)',
405
+ enum: [
406
+ 'cash',
407
+ 'investment',
408
+ 'credit_card',
409
+ 'loan',
410
+ 'payable_tax',
411
+ 'other'
412
+ ],
413
+ example: 'investment'
414
+ },
415
+ assetClass: {
416
+ type: 'string',
417
+ description:
418
+ 'Asset class (LIQUIDITY/EQUITY/.../LIABILITY), derived at read time from classification rules',
419
+ enum: [
420
+ 'LIQUIDITY',
421
+ 'EQUITY',
422
+ 'FIXED_INCOME',
423
+ 'PRECIOUS_METALS',
424
+ 'COMMODITY',
425
+ 'INSURANCE',
426
+ 'ALTERNATIVE_INVESTMENT',
427
+ 'PERSONAL_ASSETS',
428
+ 'LIABILITY',
429
+ 'REAL_ESTATE',
430
+ 'INDEX'
431
+ ]
432
+ },
433
+ assetSubClass: {
434
+ type: 'string',
435
+ description:
436
+ 'Asset sub-class (product type, derived at read time from classification rules)',
437
+ example: 'STOCK'
398
438
  }
399
439
  },
400
- required: ['path', 'type', 'description', 'tags', 'icon']
440
+ required: ['path', 'type', 'description', 'tags', 'icon', 'productCategory']
401
441
  } as const;
402
442
 
403
443
  export const $AccountStandardListResponseDto = {
@@ -736,7 +776,7 @@ export const $PostingResponseDto = {
736
776
  units: {
737
777
  type: 'string',
738
778
  description:
739
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
779
+ 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned. Carries the raw Beancount sign (credit-normal accounts such as Income post negative — the accounting truth, ADR-0126); renderers must not infer economic semantics from this sign.',
740
780
  example: '100.50'
741
781
  },
742
782
  currency: {
@@ -1102,7 +1142,7 @@ export const $PostingDetailDto = {
1102
1142
  units: {
1103
1143
  type: 'string',
1104
1144
  description:
1105
- 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned.',
1145
+ 'Amount as decimal string. Typed optional but always present in responses: interpolation fills any MISSING posting before it is persisted or returned. Carries the raw Beancount sign (credit-normal accounts such as Income post negative — the accounting truth, ADR-0126); renderers must not infer economic semantics from this sign.',
1106
1146
  example: '100.50'
1107
1147
  },
1108
1148
  currency: {
@@ -1286,6 +1326,147 @@ export const $TransactionDetailDto = {
1286
1326
  ]
1287
1327
  } as const;
1288
1328
 
1329
+ export const $TransactionListItemDto = {
1330
+ type: 'object',
1331
+ properties: {
1332
+ id: {
1333
+ type: 'string',
1334
+ description: 'Transaction ID',
1335
+ example: 'clh1234567890abcdef'
1336
+ },
1337
+ date: {
1338
+ type: 'string',
1339
+ description: 'Transaction date',
1340
+ example: '2024-11-28'
1341
+ },
1342
+ flag: {
1343
+ type: 'string',
1344
+ description: 'Transaction flag',
1345
+ enum: [
1346
+ 'CLEARED',
1347
+ 'PENDING',
1348
+ 'PADDING',
1349
+ 'SUMMARIZE',
1350
+ 'TRANSFER',
1351
+ 'CONVERSIONS'
1352
+ ],
1353
+ example: 'CLEARED'
1354
+ },
1355
+ customFlag: {
1356
+ type: 'string',
1357
+ description: 'Custom flag (if not using standard flags)',
1358
+ example: 'R'
1359
+ },
1360
+ payee: {
1361
+ type: 'string',
1362
+ description: 'Payee name',
1363
+ example: 'Whole Foods Market'
1364
+ },
1365
+ narration: {
1366
+ type: 'string',
1367
+ description: 'Transaction narration',
1368
+ example: 'Grocery shopping'
1369
+ },
1370
+ tags: {
1371
+ description: 'Transaction tags',
1372
+ example: ['groceries'],
1373
+ type: 'array',
1374
+ items: {
1375
+ type: 'string'
1376
+ }
1377
+ },
1378
+ links: {
1379
+ description: 'Transaction links',
1380
+ example: ['invoice-2024-001'],
1381
+ type: 'array',
1382
+ items: {
1383
+ type: 'string'
1384
+ }
1385
+ },
1386
+ meta: {
1387
+ type: 'object',
1388
+ description: 'Transaction metadata'
1389
+ },
1390
+ status: {
1391
+ type: 'string',
1392
+ description: 'Transaction status',
1393
+ enum: ['ACTIVE', 'VOIDED', 'SUPERSEDED'],
1394
+ example: 'ACTIVE'
1395
+ },
1396
+ sourceType: {
1397
+ type: 'string',
1398
+ description:
1399
+ 'Source type (free-form string from transaction metadata, e.g. import, api)'
1400
+ },
1401
+ sourcePlatform: {
1402
+ type: 'string',
1403
+ description: 'Source platform (e.g., alipay, wechat)',
1404
+ example: 'alipay'
1405
+ },
1406
+ postings: {
1407
+ description: 'Transaction postings',
1408
+ type: 'array',
1409
+ items: {
1410
+ $ref: '#/components/schemas/PostingDetailDto'
1411
+ }
1412
+ },
1413
+ createdAt: {
1414
+ type: 'string',
1415
+ description: 'Created at timestamp',
1416
+ example: '2024-11-28T10:30:00.000Z'
1417
+ },
1418
+ voidedAt: {
1419
+ type: 'string',
1420
+ description: 'Voided at timestamp (if voided)',
1421
+ example: '2024-11-29T15:00:00.000Z'
1422
+ },
1423
+ voidedBy: {
1424
+ type: 'string',
1425
+ description: 'User ID who voided this transaction',
1426
+ example: 'clh1234567890abcdef'
1427
+ },
1428
+ correctionReason: {
1429
+ type: 'string',
1430
+ description: 'Correction reason (if voided or superseded)',
1431
+ example: 'Duplicate entry'
1432
+ },
1433
+ supersededBy: {
1434
+ type: 'string',
1435
+ description:
1436
+ 'ID of the transaction that supersedes this one (set when status=SUPERSEDED)',
1437
+ example: 'clh1234567890abcdef'
1438
+ },
1439
+ originalTxn: {
1440
+ type: 'string',
1441
+ description:
1442
+ 'ID of the transaction this one corrected/replaced (back-link on the replacement)',
1443
+ example: 'clh1234567890abcdef'
1444
+ },
1445
+ viewpointAmount: {
1446
+ type: 'string',
1447
+ description:
1448
+ 'Row amount under the request viewpoint (ADR-0126). Category viewpoint (category + flow): per-leg sign-normalized sum over the category account set (Income-root legs negated, Expenses-root identity) — positive under normal booking but NOT clamped (explicit negative expense legs and net-flip refund months stay negative). No viewpoint (plain list / search, no accountId): wallet money-flow net = raw-sign sum over cost-less Assets/Liabilities legs (income positive, expenses negative, transfers net ~0); color cue is the wallet sign (net < 0 = wealth-decreasing). Status-orthogonal: audit views match too (ADR-0128 amount-as-matching-key). Omitted under the account viewpoint (incl. dual) and for rows with no wallet leg.',
1449
+ example: '10000.00'
1450
+ },
1451
+ viewpointCurrency: {
1452
+ type: 'string',
1453
+ description:
1454
+ 'Currency of viewpointAmount. A row spanning multiple currencies takes the largest-magnitude currency group (known simplification, ADR-0126).',
1455
+ example: 'CNY'
1456
+ }
1457
+ },
1458
+ required: [
1459
+ 'id',
1460
+ 'date',
1461
+ 'narration',
1462
+ 'tags',
1463
+ 'links',
1464
+ 'status',
1465
+ 'postings',
1466
+ 'createdAt'
1467
+ ]
1468
+ } as const;
1469
+
1289
1470
  export const $BalanceByCurrencyDto = {
1290
1471
  type: 'object',
1291
1472
  properties: {
@@ -1331,7 +1512,7 @@ export const $TransactionListSummaryDto = {
1331
1512
  totalAmount: {
1332
1513
  type: 'string',
1333
1514
  description:
1334
- 'Partial converted total in base currency (rated currencies only, raw Beancount sign). When warnings is non-empty this excludes currencies missing an FX rate; may be "0.00" if ALL non-base currencies lack a rate. Converted at the dateTo (or current) available rate.',
1515
+ 'Partial converted total in base currency (rated currencies only). Sign by viewpoint (ADR-0126): account viewpoint keeps the raw Beancount sign (income negative); category viewpoint is per-leg sign-normalized (Income legs negated, Expenses legs identity — positive under normal booking, not clamped). When warnings is non-empty this excludes currencies missing an FX rate; may be "0.00" if ALL non-base currencies lack a rate. Converted at the dateTo (or current) available rate.',
1335
1516
  example: '-6000.00'
1336
1517
  },
1337
1518
  currency: {
@@ -1357,6 +1538,26 @@ export const $TransactionListSummaryDto = {
1357
1538
  required: ['totalAmount', 'currency', 'balanceByCurrency']
1358
1539
  } as const;
1359
1540
 
1541
+ export const $TransactionListViewpointDto = {
1542
+ type: 'object',
1543
+ properties: {
1544
+ type: {
1545
+ type: 'string',
1546
+ description:
1547
+ 'Viewpoint type (only category drill-down carries a viewpoint today)',
1548
+ enum: ['category'],
1549
+ example: 'category'
1550
+ },
1551
+ flow: {
1552
+ type: 'string',
1553
+ description: 'Flow root the category account set is restricted to',
1554
+ enum: ['income', 'expense'],
1555
+ example: 'expense'
1556
+ }
1557
+ },
1558
+ required: ['type', 'flow']
1559
+ } as const;
1560
+
1360
1561
  export const $TransactionListResponseDto = {
1361
1562
  type: 'object',
1362
1563
  properties: {
@@ -1364,7 +1565,7 @@ export const $TransactionListResponseDto = {
1364
1565
  description: 'List of transactions',
1365
1566
  type: 'array',
1366
1567
  items: {
1367
- $ref: '#/components/schemas/TransactionDetailDto'
1568
+ $ref: '#/components/schemas/TransactionListItemDto'
1368
1569
  }
1369
1570
  },
1370
1571
  total: {
@@ -1390,6 +1591,15 @@ export const $TransactionListResponseDto = {
1390
1591
  $ref: '#/components/schemas/TransactionListSummaryDto'
1391
1592
  }
1392
1593
  ]
1594
+ },
1595
+ viewpoint: {
1596
+ description:
1597
+ 'Viewpoint metadata (ADR-0126). Present only for a single category filter (category + flow, no accountId); dual-perspective requests are viewpoint-less (raw signs, no viewpointAmount).',
1598
+ allOf: [
1599
+ {
1600
+ $ref: '#/components/schemas/TransactionListViewpointDto'
1601
+ }
1602
+ ]
1393
1603
  }
1394
1604
  },
1395
1605
  required: ['data', 'total', 'limit', 'offset']
@@ -4083,6 +4293,50 @@ export const $DeleteOwnUserDto = {
4083
4293
  required: ['accessToken']
4084
4294
  } as const;
4085
4295
 
4296
+ export const $UserSettingsResponseDto = {
4297
+ type: 'object',
4298
+ properties: {
4299
+ baseCurrency: {
4300
+ type: 'string',
4301
+ description:
4302
+ 'Base currency (ISO 4217) for net-worth/report aggregation. Independent of region (ADR-0006).',
4303
+ example: 'USD',
4304
+ nullable: true
4305
+ }
4306
+ },
4307
+ required: ['baseCurrency']
4308
+ } as const;
4309
+
4310
+ export const $UserResponseDto = {
4311
+ type: 'object',
4312
+ properties: {
4313
+ id: {
4314
+ type: 'string',
4315
+ description: 'User ID'
4316
+ },
4317
+ role: {
4318
+ type: 'string',
4319
+ description: 'Assigned user role'
4320
+ },
4321
+ permissions: {
4322
+ description: 'Permission strings',
4323
+ type: 'array',
4324
+ items: {
4325
+ type: 'string'
4326
+ }
4327
+ },
4328
+ settings: {
4329
+ description: 'User settings',
4330
+ allOf: [
4331
+ {
4332
+ $ref: '#/components/schemas/UserSettingsResponseDto'
4333
+ }
4334
+ ]
4335
+ }
4336
+ },
4337
+ required: ['id', 'role', 'permissions', 'settings']
4338
+ } as const;
4339
+
4086
4340
  export const $SignupDto = {
4087
4341
  type: 'object',
4088
4342
  properties: {
@@ -4888,6 +5142,69 @@ export const $TestRuleResponseDto = {
4888
5142
  required: ['ruleId', 'matches', 'confidence', 'matchDetails']
4889
5143
  } as const;
4890
5144
 
5145
+ export const $CategoryCatalogEntryDto = {
5146
+ type: 'object',
5147
+ properties: {
5148
+ slug: {
5149
+ type: 'string',
5150
+ description: 'Category slug (single source-of-truth)',
5151
+ example: 'food'
5152
+ },
5153
+ scenario: {
5154
+ type: 'string',
5155
+ description: 'Display scenario group (maps to frontend picker _scenario)',
5156
+ enum: [
5157
+ 'expense',
5158
+ 'income',
5159
+ 'investment',
5160
+ 'banking',
5161
+ 'transfer',
5162
+ 'payment'
5163
+ ],
5164
+ example: 'expense'
5165
+ },
5166
+ icon: {
5167
+ type: 'string',
5168
+ description: 'Lucide icon name',
5169
+ example: 'utensils'
5170
+ },
5171
+ regions: {
5172
+ description: "Applicable regions ('*' = all, 'cn' = CN-only)",
5173
+ example: ['*'],
5174
+ type: 'array',
5175
+ items: {
5176
+ type: 'string'
5177
+ }
5178
+ }
5179
+ },
5180
+ required: ['slug', 'scenario', 'icon', 'regions']
5181
+ } as const;
5182
+
5183
+ export const $CategoryCatalogListResponseDto = {
5184
+ type: 'object',
5185
+ properties: {
5186
+ items: {
5187
+ description: 'Category entries (region-scoped, query-filtered)',
5188
+ type: 'array',
5189
+ items: {
5190
+ $ref: '#/components/schemas/CategoryCatalogEntryDto'
5191
+ }
5192
+ },
5193
+ total: {
5194
+ type: 'number',
5195
+ description:
5196
+ 'Total category entries for the region (before query filtering)',
5197
+ example: 30
5198
+ },
5199
+ region: {
5200
+ type: 'string',
5201
+ description: 'Region code',
5202
+ example: 'cn'
5203
+ }
5204
+ },
5205
+ required: ['items', 'total', 'region']
5206
+ } as const;
5207
+
4891
5208
  export const $CreateBeanEventDto = {
4892
5209
  type: 'object',
4893
5210
  properties: {
@@ -5630,7 +5947,8 @@ export const $UpdateMapperDefaultsDto = {
5630
5947
  type: 'string',
5631
5948
  description: 'Source account for transactions (Beancount format)',
5632
5949
  example: 'Assets:CN:Alipay:Balance',
5633
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
5950
+ pattern:
5951
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5634
5952
  },
5635
5953
  currency: {
5636
5954
  type: 'string',
@@ -5644,13 +5962,15 @@ export const $UpdateMapperDefaultsDto = {
5644
5962
  type: 'string',
5645
5963
  description: 'Default expense account (optional)',
5646
5964
  example: 'Expenses:Unknown',
5647
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
5965
+ pattern:
5966
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5648
5967
  },
5649
5968
  incomeAccount: {
5650
5969
  type: 'string',
5651
5970
  description: 'Default income account (optional)',
5652
5971
  example: 'Income:Unknown',
5653
- pattern: '^[A-Z][a-zA-Z0-9-]*:[a-zA-Z0-9-:]+$'
5972
+ pattern:
5973
+ '^(Assets|Liabilities|Income|Expenses|Equity)(:[A-Za-z0-9][A-Za-z0-9-]*)+$'
5654
5974
  },
5655
5975
  methodAccountMapping: {
5656
5976
  type: 'object',
@@ -5707,12 +6027,14 @@ export const $ProviderSyncConfigDto = {
5707
6027
  },
5708
6028
  defaultExpenseAccount: {
5709
6029
  type: 'string',
5710
- description: 'Default expense account for the second posting',
6030
+ description:
6031
+ 'Default expense account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5711
6032
  example: 'Expenses:Unknown'
5712
6033
  },
5713
6034
  defaultIncomeAccount: {
5714
6035
  type: 'string',
5715
- description: 'Default income account for the second posting',
6036
+ description:
6037
+ 'Default income account for the second posting. Omit when no real default exists; the pipeline routes to Review via the Uncategorized sentinel (#618).',
5716
6038
  example: 'Income:Unknown'
5717
6039
  },
5718
6040
  filterPending: {
@@ -5727,12 +6049,7 @@ export const $ProviderSyncConfigDto = {
5727
6049
  example: 'acc_gocardless_001'
5728
6050
  }
5729
6051
  },
5730
- required: [
5731
- 'sourceAccount',
5732
- 'defaultCurrency',
5733
- 'defaultExpenseAccount',
5734
- 'defaultIncomeAccount'
5735
- ]
6052
+ required: ['sourceAccount', 'defaultCurrency']
5736
6053
  } as const;
5737
6054
 
5738
6055
  export const $ProviderSyncDto = {
@@ -5942,15 +6259,105 @@ export const $UncoveredFormatMissDto = {
5942
6259
  properties: {}
5943
6260
  } as const;
5944
6261
 
6262
+ export const $ClientParsedDataDto = {
6263
+ type: 'object',
6264
+ properties: {
6265
+ amount: {
6266
+ type: 'number',
6267
+ description: 'Transaction amount',
6268
+ example: 35
6269
+ },
6270
+ currency: {
6271
+ type: 'string',
6272
+ description: 'Currency code',
6273
+ example: 'CNY'
6274
+ },
6275
+ date: {
6276
+ type: 'string',
6277
+ description: 'Transaction date (ISO 8601)',
6278
+ example: '2026-08-15'
6279
+ },
6280
+ payee: {
6281
+ type: 'string',
6282
+ description: 'Payee/merchant name',
6283
+ example: 'Starbucks'
6284
+ },
6285
+ narration: {
6286
+ type: 'string',
6287
+ description: 'Transaction narration'
6288
+ },
6289
+ category: {
6290
+ type: 'string',
6291
+ description: 'Category slug',
6292
+ example: 'food_restaurant'
6293
+ },
6294
+ incomeType: {
6295
+ type: 'string',
6296
+ description: 'Income type',
6297
+ example: 'Salary'
6298
+ },
6299
+ incomeSource: {
6300
+ type: 'string',
6301
+ description: 'Income source',
6302
+ example: 'Anthropic Inc.'
6303
+ },
6304
+ symbol: {
6305
+ type: 'string',
6306
+ description: 'Security symbol code (e.g., 600519, AAPL)',
6307
+ example: 'AAPL'
6308
+ },
6309
+ quantity: {
6310
+ type: 'number',
6311
+ description: 'Quantity of shares/units',
6312
+ example: 100
6313
+ },
6314
+ price: {
6315
+ type: 'number',
6316
+ description: 'Unit price per share/unit',
6317
+ example: 1900
6318
+ },
6319
+ investmentAction: {
6320
+ type: 'string',
6321
+ description: 'Investment action',
6322
+ enum: ['buy', 'sell'],
6323
+ example: 'buy'
6324
+ },
6325
+ paymentSource: {
6326
+ type: 'string',
6327
+ description: 'Payment source: asset (default) or liability (credit card)',
6328
+ enum: ['asset', 'liability'],
6329
+ example: 'asset'
6330
+ },
6331
+ liabilityHint: {
6332
+ type: 'string',
6333
+ description: 'Liability account hint (CreditCard/Huabei/Baitiao)',
6334
+ example: 'CreditCard'
6335
+ },
6336
+ warning: {
6337
+ type: 'string',
6338
+ description:
6339
+ 'Display-only warning from the prior response; accepted but ignored.',
6340
+ example: 'Cross-currency settlement applies.'
6341
+ }
6342
+ }
6343
+ } as const;
6344
+
5945
6345
  export const $ProcessNlpDto = {
5946
6346
  type: 'object',
5947
6347
  properties: {
5948
6348
  message: {
5949
6349
  type: 'string',
5950
- description: 'Natural language text describing a transaction (Chinese)',
5951
- example: 'yesterday Starbucks spent 35 yuan',
6350
+ description:
6351
+ 'Natural language text describing a transaction. Optional when `confirm` is true (structured confirm); otherwise required.',
6352
+ example: 'Starbucks 35',
5952
6353
  maxLength: 500
5953
6354
  },
6355
+ confirm: {
6356
+ type: 'boolean',
6357
+ description:
6358
+ 'Structured confirm signal — bypasses NL confirm-word matching when true. Send parsedData field edits alongside. The NL word-list path is the fallback.',
6359
+ example: true
6360
+ },
5954
6361
  sessionId: {
5955
6362
  type: 'string',
5956
6363
  description:
@@ -5958,14 +6365,18 @@ export const $ProcessNlpDto = {
5958
6365
  example: 'session_abc123'
5959
6366
  },
5960
6367
  parsedData: {
5961
- type: 'object',
5962
6368
  description:
5963
6369
  'Parsed data from previous NLP response for session recovery. Send back the parsedData received in confirm_payee/confirm responses.',
5964
6370
  example: {
5965
6371
  amount: 35,
5966
6372
  currency: 'CNY',
5967
6373
  payee: 'Starbucks'
5968
- }
6374
+ },
6375
+ allOf: [
6376
+ {
6377
+ $ref: '#/components/schemas/ClientParsedDataDto'
6378
+ }
6379
+ ]
5969
6380
  },
5970
6381
  selectedRuleId: {
5971
6382
  type: 'string',
@@ -5976,11 +6387,10 @@ export const $ProcessNlpDto = {
5976
6387
  selectedAccount: {
5977
6388
  type: 'string',
5978
6389
  description:
5979
- 'confirm_account echo-back: account path selected from the prior confirm_account response (suggestedAccount, similarAccounts[i], or a typed path). Applied directly when the session is confirming_account — no NL re-parse.',
6390
+ 'confirm_account echo-back: account path selected from the prior confirm_account response (suggestedAccount, similarAccounts[i].path, or a typed path). Applied directly when the session is confirming_account — no NL re-parse.',
5980
6391
  example: 'Expenses:Food:Coffee'
5981
6392
  }
5982
- },
5983
- required: ['message']
6393
+ }
5984
6394
  } as const;
5985
6395
 
5986
6396
  export const $NlpTransactionInfoDto = {
@@ -6292,6 +6702,24 @@ export const $NlpRuleConfirmationDataDto = {
6292
6702
  ]
6293
6703
  } as const;
6294
6704
 
6705
+ export const $NlpAccountCandidateDto = {
6706
+ type: 'object',
6707
+ properties: {
6708
+ path: {
6709
+ type: 'string',
6710
+ description: 'Canonical beancount account path (echo back on selection)',
6711
+ example: 'Expenses:Food:Dining'
6712
+ },
6713
+ name: {
6714
+ type: 'string',
6715
+ description:
6716
+ 'Localized display name (ADR-0114 read-time projection, user locale)',
6717
+ example: '餐饮'
6718
+ }
6719
+ },
6720
+ required: ['path', 'name']
6721
+ } as const;
6722
+
6295
6723
  export const $NlpAccountConfirmationDataDto = {
6296
6724
  type: 'object',
6297
6725
  properties: {
@@ -6307,10 +6735,11 @@ export const $NlpAccountConfirmationDataDto = {
6307
6735
  example: 'Expenses:Food:Drinks'
6308
6736
  },
6309
6737
  similarAccounts: {
6310
- description: 'Similar accounts for user selection',
6738
+ description:
6739
+ 'Similar accounts for user selection (path + localized name, #680)',
6311
6740
  type: 'array',
6312
6741
  items: {
6313
- type: 'string'
6742
+ $ref: '#/components/schemas/NlpAccountCandidateDto'
6314
6743
  }
6315
6744
  },
6316
6745
  errorMessage: {
@@ -6598,7 +7027,7 @@ export const $NlpResponseDto = {
6598
7027
  type: 'string',
6599
7028
  description:
6600
7029
  'Asset sub-type (only present when intent is "asset"). Determines which asset-related form to render.',
6601
- enum: ['transfer', 'banking', 'investment'],
7030
+ enum: ['transfer', 'banking', 'investment', 'lend', 'lend_collect'],
6602
7031
  example: 'investment'
6603
7032
  },
6604
7033
  liabilitySubType: {
@@ -6801,13 +7230,26 @@ export const $PlatformListItemDto = {
6801
7230
  suggestedSegment: {
6802
7231
  type: 'string',
6803
7232
  description:
6804
- 'Suggested path segment — canonical with first char uppercased (ACC_COMP_NAME_RE)'
7233
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
6805
7234
  },
6806
7235
  logoUrl: {
6807
7236
  type: 'string',
6808
7237
  description: 'Logo URL',
6809
7238
  nullable: true
6810
7239
  },
7240
+ countryCode: {
7241
+ type: 'string',
7242
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7243
+ example: 'CN',
7244
+ nullable: true
7245
+ },
7246
+ category: {
7247
+ type: 'string',
7248
+ description:
7249
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7250
+ nullable: true,
7251
+ example: 'DigitalWallet'
7252
+ },
6811
7253
  isBound: {
6812
7254
  type: 'boolean',
6813
7255
  description: 'Whether user has accounts using this platform'
@@ -6821,6 +7263,8 @@ export const $PlatformListItemDto = {
6821
7263
  'canonical',
6822
7264
  'suggestedSegment',
6823
7265
  'logoUrl',
7266
+ 'countryCode',
7267
+ 'category',
6824
7268
  'isBound'
6825
7269
  ]
6826
7270
  } as const;
@@ -6856,13 +7300,26 @@ export const $PlatformMatchResultDto = {
6856
7300
  suggestedSegment: {
6857
7301
  type: 'string',
6858
7302
  description:
6859
- 'Suggested path segment — canonical, already in ACCOUNT_RE format'
7303
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
6860
7304
  },
6861
7305
  logoUrl: {
6862
7306
  type: 'string',
6863
7307
  description: 'Logo URL',
6864
7308
  nullable: true
6865
7309
  },
7310
+ countryCode: {
7311
+ type: 'string',
7312
+ description: 'ISO 3166-1 alpha-2 (UPPERCASE); null = global platform',
7313
+ example: 'CN',
7314
+ nullable: true
7315
+ },
7316
+ category: {
7317
+ type: 'string',
7318
+ description:
7319
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank). null = no region-aware suggestion; fall back to type.',
7320
+ nullable: true,
7321
+ example: 'DigitalWallet'
7322
+ },
6866
7323
  matchType: {
6867
7324
  type: 'string',
6868
7325
  description: "How this row matched: 'exact' > 'prefix' > 'substring'",
@@ -6876,6 +7333,8 @@ export const $PlatformMatchResultDto = {
6876
7333
  'type',
6877
7334
  'suggestedSegment',
6878
7335
  'logoUrl',
7336
+ 'countryCode',
7337
+ 'category',
6879
7338
  'matchType'
6880
7339
  ]
6881
7340
  } as const;
@@ -8125,6 +8584,216 @@ export const $AnonymousLoginResponseDto = {
8125
8584
  required: ['authToken']
8126
8585
  } as const;
8127
8586
 
8587
+ export const $ParserContributionMetaDto = {
8588
+ type: 'object',
8589
+ properties: {
8590
+ institution: {
8591
+ type: 'string',
8592
+ description: 'Institution slug (lowercase kebab-case)',
8593
+ pattern: '^[a-z0-9]+(-[a-z0-9]+)*$',
8594
+ example: 'icbc'
8595
+ },
8596
+ region: {
8597
+ type: 'string',
8598
+ enum: [
8599
+ 'cn',
8600
+ 'us',
8601
+ 'de',
8602
+ 'fr',
8603
+ 'gb',
8604
+ 'hk',
8605
+ 'jp',
8606
+ 'sg',
8607
+ 'au',
8608
+ 'ca',
8609
+ 'other'
8610
+ ]
8611
+ },
8612
+ accountType: {
8613
+ type: 'string',
8614
+ enum: ['checking', 'savings', 'credit', 'debit', 'investment']
8615
+ },
8616
+ format: {
8617
+ type: 'string',
8618
+ enum: ['csv', 'xlsx', 'pdf', 'ofx', 'qif']
8619
+ },
8620
+ institutionDisplayName: {
8621
+ type: 'string',
8622
+ example: '中国工商银行'
8623
+ },
8624
+ encoding: {
8625
+ type: 'string',
8626
+ example: 'utf-8'
8627
+ },
8628
+ delimiter: {
8629
+ type: 'string',
8630
+ description: 'CSV delimiter character: ",", ";", "\\t" or "|"'
8631
+ },
8632
+ headerRows: {
8633
+ type: 'number',
8634
+ default: 1,
8635
+ description: 'Header row count; the client omits the field when it is 1'
8636
+ },
8637
+ notes: {
8638
+ type: 'string',
8639
+ maxLength: 2000
8640
+ }
8641
+ },
8642
+ required: ['institution', 'region', 'accountType', 'format']
8643
+ } as const;
8644
+
8645
+ export const $ParserContributionSamplesDto = {
8646
+ type: 'object',
8647
+ properties: {
8648
+ rows: {
8649
+ description:
8650
+ 'Client-sanitized sample rows (key = column name, value = cell)',
8651
+ type: 'array',
8652
+ items: {
8653
+ type: 'object'
8654
+ }
8655
+ },
8656
+ rawHeaders: {
8657
+ type: 'array',
8658
+ items: {
8659
+ type: 'string'
8660
+ }
8661
+ }
8662
+ },
8663
+ required: ['rows']
8664
+ } as const;
8665
+
8666
+ export const $FieldHintDto = {
8667
+ type: 'object',
8668
+ properties: {
8669
+ columnName: {
8670
+ type: 'string',
8671
+ example: '交易日期'
8672
+ },
8673
+ format: {
8674
+ type: 'string',
8675
+ description: 'Date format, e.g. yyyy-MM-dd HH:mm',
8676
+ example: 'yyyy-MM-dd'
8677
+ },
8678
+ signConvention: {
8679
+ type: 'string',
8680
+ enum: ['negative-expense', 'positive-expense', 'separate-columns']
8681
+ },
8682
+ creditColumn: {
8683
+ type: 'string'
8684
+ },
8685
+ debitColumn: {
8686
+ type: 'string'
8687
+ }
8688
+ },
8689
+ required: ['columnName']
8690
+ } as const;
8691
+
8692
+ export const $ParserContributionFieldHintsDto = {
8693
+ type: 'object',
8694
+ properties: {
8695
+ date: {
8696
+ $ref: '#/components/schemas/FieldHintDto'
8697
+ },
8698
+ amount: {
8699
+ $ref: '#/components/schemas/FieldHintDto'
8700
+ },
8701
+ description: {
8702
+ $ref: '#/components/schemas/FieldHintDto'
8703
+ },
8704
+ balance: {
8705
+ $ref: '#/components/schemas/FieldHintDto'
8706
+ },
8707
+ payee: {
8708
+ $ref: '#/components/schemas/FieldHintDto'
8709
+ },
8710
+ reference: {
8711
+ $ref: '#/components/schemas/FieldHintDto'
8712
+ },
8713
+ category: {
8714
+ $ref: '#/components/schemas/FieldHintDto'
8715
+ }
8716
+ },
8717
+ required: ['date', 'amount']
8718
+ } as const;
8719
+
8720
+ export const $ExpectedTransactionDto = {
8721
+ type: 'object',
8722
+ properties: {
8723
+ date: {
8724
+ type: 'string',
8725
+ example: '2026-08-01'
8726
+ },
8727
+ amount: {
8728
+ type: 'number',
8729
+ example: -45.5
8730
+ },
8731
+ description: {
8732
+ type: 'string',
8733
+ example: '星巴克-***店'
8734
+ },
8735
+ payee: {
8736
+ type: 'string'
8737
+ },
8738
+ category: {
8739
+ type: 'string'
8740
+ }
8741
+ },
8742
+ required: ['date', 'amount', 'description']
8743
+ } as const;
8744
+
8745
+ export const $ParserContributionExamplesDto = {
8746
+ type: 'object',
8747
+ properties: {
8748
+ expectedTransactions: {
8749
+ type: 'array',
8750
+ items: {
8751
+ $ref: '#/components/schemas/ExpectedTransactionDto'
8752
+ }
8753
+ }
8754
+ },
8755
+ required: ['expectedTransactions']
8756
+ } as const;
8757
+
8758
+ export const $ParserContributionRequestDto = {
8759
+ type: 'object',
8760
+ properties: {
8761
+ meta: {
8762
+ $ref: '#/components/schemas/ParserContributionMetaDto'
8763
+ },
8764
+ samples: {
8765
+ $ref: '#/components/schemas/ParserContributionSamplesDto'
8766
+ },
8767
+ fieldHints: {
8768
+ $ref: '#/components/schemas/ParserContributionFieldHintsDto'
8769
+ },
8770
+ examples: {
8771
+ description: 'Omitted entirely by the client when empty',
8772
+ allOf: [
8773
+ {
8774
+ $ref: '#/components/schemas/ParserContributionExamplesDto'
8775
+ }
8776
+ ]
8777
+ }
8778
+ },
8779
+ required: ['meta', 'samples', 'fieldHints']
8780
+ } as const;
8781
+
8782
+ export const $ParserContributionRelayResponseDto = {
8783
+ type: 'object',
8784
+ properties: {
8785
+ issueUrl: {
8786
+ type: 'string',
8787
+ example: 'https://github.com/fire-zu/firela-vlt/issues/42'
8788
+ },
8789
+ issueNumber: {
8790
+ type: 'number',
8791
+ example: 42
8792
+ }
8793
+ },
8794
+ required: ['issueUrl', 'issueNumber']
8795
+ } as const;
8796
+
8128
8797
  export const $SymbolSearchResultDto = {
8129
8798
  type: 'object',
8130
8799
  properties: {