@firela/api-types 0.0.0-canary.69a6df79 → 0.0.0-canary.6af2ffd3

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:
@@ -181,7 +189,8 @@ export const $AccountResponseDto = {
181
189
  },
182
190
  displayName: {
183
191
  type: 'string',
184
- 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)',
185
194
  example: 'Checking'
186
195
  },
187
196
  icon: {
@@ -197,7 +206,7 @@ export const $AccountResponseDto = {
197
206
  }
198
207
  },
199
208
  platformId: {
200
- type: 'object',
209
+ type: 'string',
201
210
  description: 'Platform ID (null if unbound)',
202
211
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
203
212
  },
@@ -277,6 +286,14 @@ export const $UpdateAccountDto = {
277
286
  description: 'Icon identifier',
278
287
  example: 'bank-custom'
279
288
  },
289
+ displayName: {
290
+ type: 'string',
291
+ description:
292
+ 'User-set display name override (null = clear the override and fall back to the derived name, omit = unchanged)',
293
+ nullable: true,
294
+ maxLength: 50,
295
+ example: 'Salary card'
296
+ },
280
297
  openDirectiveMeta: {
281
298
  type: 'object',
282
299
  description:
@@ -377,16 +394,43 @@ export const $AccountStandardResponseDto = {
377
394
  },
378
395
  name: {
379
396
  type: 'string',
380
- description: 'Short localized display name',
397
+ description:
398
+ '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).',
381
399
  example: 'Housing Fund'
382
400
  },
401
+ aliases: {
402
+ description:
403
+ '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.',
404
+ example: ['Alipay', 'WeChat Pay'],
405
+ type: 'array',
406
+ items: {
407
+ type: 'string'
408
+ }
409
+ },
410
+ searchTerms: {
411
+ description:
412
+ '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).',
413
+ example: ['yinhangka', 'jiejika'],
414
+ type: 'array',
415
+ items: {
416
+ type: 'string'
417
+ }
418
+ },
419
+ currency: {
420
+ type: 'string',
421
+ description:
422
+ '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).',
423
+ example: 'HKD'
424
+ },
383
425
  description: {
384
426
  type: 'string',
385
- description: 'Account description (stable semantics only)',
427
+ description:
428
+ '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).',
386
429
  example: 'ICBC checking account for daily transactions'
387
430
  },
388
431
  tags: {
389
- description: 'Account tags for categorization',
432
+ description:
433
+ 'Account tags for categorization — structured metadata delivered verbatim (not localized, not xlf-managed). ADR-0131 class A.',
390
434
  example: ['bank', 'checking', 'primary'],
391
435
  type: 'array',
392
436
  items: {
@@ -498,7 +542,10 @@ export const $RegionConfigDto = {
498
542
  },
499
543
  locale: {
500
544
  type: 'string',
501
- example: 'de-DE'
545
+ example: 'de-DE',
546
+ pattern: '^[a-z]{2,8}-[A-Z]{2}$',
547
+ description:
548
+ "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)"
502
549
  }
503
550
  },
504
551
  required: ['currency', 'dateFormat', 'locale']
@@ -511,6 +558,12 @@ export const $RegionInfoDto = {
511
558
  type: 'string',
512
559
  example: 'de'
513
560
  },
561
+ open: {
562
+ type: 'boolean',
563
+ example: true,
564
+ description:
565
+ '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.'
566
+ },
514
567
  displayName: {
515
568
  type: 'string',
516
569
  example: 'Germany'
@@ -529,7 +582,7 @@ export const $RegionInfoDto = {
529
582
  $ref: '#/components/schemas/RegionConfigDto'
530
583
  }
531
584
  },
532
- required: ['code', 'displayName', 'chain', 'config']
585
+ required: ['code', 'open', 'displayName', 'chain', 'config']
533
586
  } as const;
534
587
 
535
588
  export const $RegionsMetadataResponseDto = {
@@ -1951,13 +2004,17 @@ export const $ReviewStatsDto = {
1951
2004
  type: 'object',
1952
2005
  description: 'Count by type'
1953
2006
  },
2007
+ resolved: {
2008
+ type: 'number',
2009
+ description: 'Current count of reviews in RESOLVED status'
2010
+ },
1954
2011
  oldestPending: {
1955
2012
  format: 'date-time',
1956
2013
  type: 'string',
1957
2014
  description: 'Oldest pending review date'
1958
2015
  }
1959
2016
  },
1960
- required: ['total', 'byType']
2017
+ required: ['total', 'byType', 'resolved']
1961
2018
  } as const;
1962
2019
 
1963
2020
  export const $DecisionOptionDto = {
@@ -2510,10 +2567,10 @@ export const $UpdatePayeeDto = {
2510
2567
  meta: {
2511
2568
  type: 'object',
2512
2569
  description:
2513
- 'Metadata for extended information (location, notes, contact info, etc.). Will merge with existing metadata.',
2570
+ 'Metadata for extended information (location, notes, contact info, etc.)',
2514
2571
  example: {
2515
2572
  location: 'Zhongguancun',
2516
- note: 'Updated note',
2573
+ note: 'Near subway station',
2517
2574
  favorite: true
2518
2575
  }
2519
2576
  },
@@ -3074,568 +3131,660 @@ export const $UpdateCommodityDto = {
3074
3131
  }
3075
3132
  } as const;
3076
3133
 
3077
- export const $CreateBeanPriceDto = {
3134
+ export const $CurrencyBalanceDto = {
3078
3135
  type: 'object',
3079
3136
  properties: {
3080
3137
  currency: {
3081
3138
  type: 'string',
3082
- description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3083
- example: 'USD'
3084
- },
3085
- quoteCurrency: {
3086
- type: 'string',
3087
- description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
3139
+ description: 'ISO 4217 currency code',
3088
3140
  example: 'CNY'
3089
3141
  },
3090
- amount: {
3091
- type: 'number',
3092
- description:
3093
- 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
3094
- example: 175.5,
3095
- minimum: 0
3096
- },
3097
- date: {
3142
+ balance: {
3098
3143
  type: 'string',
3099
- description: 'Price date (ISO 8601 format)',
3100
- example: '2024-11-05'
3101
- },
3102
- metadata: {
3103
- type: 'object',
3104
- description:
3105
- 'Metadata (validated by Zod schema, max field lengths enforced)',
3106
- example: {
3107
- source: 'MANUAL',
3108
- note: 'Bank valuation report',
3109
- confidence: 0.95
3110
- }
3144
+ description: 'Balance amount',
3145
+ example: '500000.00'
3111
3146
  }
3112
3147
  },
3113
- required: ['currency', 'quoteCurrency', 'amount', 'date']
3148
+ required: ['currency', 'balance']
3114
3149
  } as const;
3115
3150
 
3116
- export const $PriceResponseDto = {
3151
+ export const $TimeSeriesPointDto = {
3117
3152
  type: 'object',
3118
3153
  properties: {
3119
- id: {
3154
+ date: {
3120
3155
  type: 'string',
3121
- description: 'Unique identifier',
3122
- example: 'uuid-123-456'
3156
+ description: 'Date in YYYY-MM-DD format',
3157
+ example: '2024-06-15'
3123
3158
  },
3124
- userId: {
3159
+ value: {
3125
3160
  type: 'string',
3126
- description: 'User ID (owner of the price)',
3127
- example: 'user-123'
3161
+ description: 'Value at this date (in base currency)',
3162
+ example: '500000.00'
3128
3163
  },
3129
- currency: {
3164
+ change: {
3130
3165
  type: 'string',
3131
- description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3132
- example: 'BTC'
3166
+ description: 'Change from previous point',
3167
+ example: '5000.00'
3133
3168
  },
3134
- quoteCurrency: {
3169
+ assets: {
3135
3170
  type: 'string',
3136
- description: 'Quote currency (pricing currency, e.g., USD, CNY)',
3137
- example: 'USD'
3138
- },
3139
- amount: {
3140
- type: 'number',
3141
- description:
3142
- 'Price amount (corresponds to Beancount Amount.number). Supports up to 15 decimal places.',
3143
- example: 50000
3171
+ description: 'Total assets at this date (in base currency)',
3172
+ example: '494338.00'
3144
3173
  },
3145
- date: {
3174
+ liabilities: {
3146
3175
  type: 'string',
3147
- description:
3148
- 'Price date (ISO 8601 format). Represents the date this price was valid.',
3149
- example: '2024-01-01',
3150
- format: 'date'
3176
+ description: 'Total liabilities at this date (in base currency)',
3177
+ example: '310098.00'
3151
3178
  },
3152
- meta: {
3153
- type: 'object',
3154
- description:
3155
- 'Metadata (corresponds to Beancount meta field). Contains source, confidence, note, etc.',
3156
- example: {
3157
- source: 'MANUAL',
3158
- note: 'User-defined price',
3159
- confidence: 1
3179
+ byCurrency: {
3180
+ description: 'Multi-currency breakdown for this point',
3181
+ type: 'array',
3182
+ items: {
3183
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3160
3184
  }
3185
+ }
3186
+ },
3187
+ required: ['date', 'value']
3188
+ } as const;
3189
+
3190
+ export const $TrendSummaryDto = {
3191
+ type: 'object',
3192
+ properties: {
3193
+ startValue: {
3194
+ type: 'string',
3195
+ description: 'Value at start of period',
3196
+ example: '450000.00'
3161
3197
  },
3162
- createdAt: {
3163
- format: 'date-time',
3198
+ endValue: {
3164
3199
  type: 'string',
3165
- description: 'Creation timestamp',
3166
- example: '2024-11-03T10:00:00Z'
3200
+ description: 'Value at end of period',
3201
+ example: '500000.00'
3167
3202
  },
3168
- updatedAt: {
3169
- format: 'date-time',
3203
+ totalChange: {
3170
3204
  type: 'string',
3171
- description: 'Last update timestamp',
3172
- example: '2024-11-03T10:00:00Z'
3205
+ description: 'Total change over period',
3206
+ example: '50000.00'
3207
+ },
3208
+ totalChangePercentage: {
3209
+ type: 'string',
3210
+ description: 'Total change percentage',
3211
+ example: '+11.11%'
3173
3212
  }
3174
3213
  },
3175
- required: [
3176
- 'id',
3177
- 'userId',
3178
- 'currency',
3179
- 'quoteCurrency',
3180
- 'amount',
3181
- 'date',
3182
- 'meta',
3183
- 'createdAt',
3184
- 'updatedAt'
3185
- ]
3214
+ required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
3186
3215
  } as const;
3187
3216
 
3188
- export const $PriceListResponseDto = {
3217
+ export const $MultiCurrencyPointDto = {
3189
3218
  type: 'object',
3190
3219
  properties: {
3191
- items: {
3192
- description: 'List of prices',
3220
+ date: {
3221
+ type: 'string',
3222
+ description: 'Date in YYYY-MM-DD format',
3223
+ example: '2024-06-15'
3224
+ },
3225
+ byCurrency: {
3226
+ description: 'Balances by currency',
3193
3227
  type: 'array',
3194
3228
  items: {
3195
- $ref: '#/components/schemas/PriceResponseDto'
3229
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3196
3230
  }
3197
- },
3198
- total: {
3199
- type: 'number',
3200
- description: 'Total number of prices',
3201
- example: 42
3202
3231
  }
3203
3232
  },
3204
- required: ['items', 'total']
3233
+ required: ['date', 'byCurrency']
3205
3234
  } as const;
3206
3235
 
3207
- export const $UpdateBeanPriceDto = {
3236
+ export const $PortfolioTrendsResponseDto = {
3208
3237
  type: 'object',
3209
3238
  properties: {
3210
- currency: {
3211
- type: 'string',
3212
- description: 'Currency being priced'
3239
+ series: {
3240
+ description: 'Time series data points',
3241
+ type: 'array',
3242
+ items: {
3243
+ $ref: '#/components/schemas/TimeSeriesPointDto'
3244
+ }
3213
3245
  },
3214
- quoteCurrency: {
3246
+ summary: {
3247
+ description: 'Period summary',
3248
+ allOf: [
3249
+ {
3250
+ $ref: '#/components/schemas/TrendSummaryDto'
3251
+ }
3252
+ ]
3253
+ },
3254
+ period: {
3215
3255
  type: 'string',
3216
- description: 'Quote currency (pricing currency)'
3256
+ description: 'Period requested',
3257
+ example: '6m'
3217
3258
  },
3218
- amount: {
3219
- type: 'number',
3220
- description: 'Price amount (MUST be >= 0 per Beancount spec)',
3221
- minimum: 0
3259
+ granularity: {
3260
+ type: 'string',
3261
+ description: 'Data granularity',
3262
+ example: 'month'
3222
3263
  },
3223
- date: {
3264
+ currency: {
3224
3265
  type: 'string',
3225
- description: 'Price date (ISO 8601 format)'
3266
+ description: 'Base currency for converted values',
3267
+ example: 'CNY'
3226
3268
  },
3227
- metadata: {
3228
- type: 'object',
3229
- description: 'Metadata'
3269
+ byCurrency: {
3270
+ description:
3271
+ 'Multi-currency time series (each point has currency breakdown)',
3272
+ type: 'array',
3273
+ items: {
3274
+ $ref: '#/components/schemas/MultiCurrencyPointDto'
3275
+ }
3276
+ },
3277
+ warnings: {
3278
+ description: 'Exchange rate warnings',
3279
+ type: 'array',
3280
+ items: {
3281
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3282
+ }
3230
3283
  }
3231
- }
3284
+ },
3285
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3232
3286
  } as const;
3233
3287
 
3234
- export const $CreateRecurringRuleDto = {
3288
+ export const $CashFlowPointDto = {
3235
3289
  type: 'object',
3236
3290
  properties: {
3237
- name: {
3291
+ month: {
3238
3292
  type: 'string',
3239
- description: 'Rule name (unique per user)',
3240
- maxLength: 100
3241
- },
3242
- icon: {
3243
- type: 'string',
3244
- description: 'Icon emoji',
3245
- maxLength: 10
3293
+ description: 'Month key (YYYY-MM)',
3294
+ example: '2024-03'
3246
3295
  },
3247
- frequency: {
3296
+ income: {
3248
3297
  type: 'string',
3249
- description: 'Recurring frequency',
3250
- enum: [
3251
- 'WEEKLY',
3252
- 'BIWEEKLY',
3253
- 'MONTHLY',
3254
- 'BIMONTHLY',
3255
- 'QUARTERLY',
3256
- 'YEARLY',
3257
- 'CUSTOM'
3258
- ]
3298
+ description: 'Income in base currency (absolute, converted)',
3299
+ example: '10000.00'
3259
3300
  },
3260
- expectedAmount: {
3261
- type: 'number',
3262
- description: 'Expected amount (positive number)',
3263
- minimum: 0
3301
+ expense: {
3302
+ type: 'string',
3303
+ description: 'Expense in base currency (absolute, converted)',
3304
+ example: '5000.00'
3264
3305
  },
3265
- expectedDay: {
3266
- type: 'number',
3267
- description: 'Expected day of month (1-31)',
3268
- minimum: 1,
3269
- maximum: 31
3306
+ netSavings: {
3307
+ type: 'string',
3308
+ description: 'netSavings = income − expense (savings positive)',
3309
+ example: '5000.00'
3310
+ }
3311
+ },
3312
+ required: ['month', 'income', 'expense', 'netSavings']
3313
+ } as const;
3314
+
3315
+ export const $CashFlowTrendSummaryDto = {
3316
+ type: 'object',
3317
+ properties: {
3318
+ totalIncome: {
3319
+ type: 'string',
3320
+ description: 'Total income across the period',
3321
+ example: '60000.00'
3270
3322
  },
3271
- customIntervalDays: {
3272
- type: 'number',
3273
- description: 'Custom interval in days (required for CUSTOM frequency)',
3274
- minimum: 1
3323
+ totalExpense: {
3324
+ type: 'string',
3325
+ description: 'Total expense across the period',
3326
+ example: '30000.00'
3275
3327
  },
3276
- currency: {
3328
+ totalNetSavings: {
3277
3329
  type: 'string',
3278
- description: 'Currency code',
3279
- default: 'CNY',
3280
- maxLength: 10
3330
+ description: 'income − expense across the period',
3331
+ example: '30000.00'
3281
3332
  },
3282
- matchPayeePattern: {
3333
+ averageMonthlyNetSavings: {
3283
3334
  type: 'string',
3284
- description: 'Payee matching pattern (supports wildcards)',
3285
- maxLength: 200
3335
+ description:
3336
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
3337
+ example: '5000.00'
3338
+ }
3339
+ },
3340
+ required: [
3341
+ 'totalIncome',
3342
+ 'totalExpense',
3343
+ 'totalNetSavings',
3344
+ 'averageMonthlyNetSavings'
3345
+ ]
3346
+ } as const;
3347
+
3348
+ export const $CashFlowTrendsResponseDto = {
3349
+ type: 'object',
3350
+ properties: {
3351
+ series: {
3352
+ description:
3353
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
3354
+ type: 'array',
3355
+ items: {
3356
+ $ref: '#/components/schemas/CashFlowPointDto'
3357
+ }
3286
3358
  },
3287
- matchAmountTolerance: {
3288
- type: 'number',
3289
- description: 'Amount tolerance percentage (0-1)',
3290
- default: 0.075,
3291
- minimum: 0,
3292
- maximum: 1
3359
+ summary: {
3360
+ description: 'Period totals',
3361
+ allOf: [
3362
+ {
3363
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
3364
+ }
3365
+ ]
3293
3366
  },
3294
- defaultExpenseAccount: {
3367
+ period: {
3295
3368
  type: 'string',
3296
- description: 'Default expense account for auto-create',
3297
- maxLength: 200
3369
+ description: 'Period requested',
3370
+ example: '6m'
3298
3371
  },
3299
- defaultPaymentAccount: {
3372
+ granularity: {
3300
3373
  type: 'string',
3301
- description: 'Default payment account for auto-create',
3302
- maxLength: 200
3374
+ description: 'Data granularity (v1 returns month buckets)',
3375
+ example: 'month'
3303
3376
  },
3304
- defaultPayee: {
3377
+ currency: {
3305
3378
  type: 'string',
3306
- description: 'Default payee for auto-create',
3307
- maxLength: 200
3379
+ description: 'Base currency for converted values',
3380
+ example: 'CNY'
3308
3381
  },
3309
- autoCreate: {
3310
- type: 'boolean',
3311
- description: 'Auto-create transaction when expected date arrives',
3312
- default: false
3382
+ warnings: {
3383
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
3384
+ type: 'array',
3385
+ items: {
3386
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3387
+ }
3388
+ }
3389
+ },
3390
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3391
+ } as const;
3392
+
3393
+ export const $GenerateSnapshotBody = {
3394
+ type: 'object',
3395
+ properties: {}
3396
+ } as const;
3397
+
3398
+ export const $GenerateSnapshotResponse = {
3399
+ type: 'object',
3400
+ properties: {}
3401
+ } as const;
3402
+
3403
+ export const $BackfillSnapshotsBody = {
3404
+ type: 'object',
3405
+ properties: {}
3406
+ } as const;
3407
+
3408
+ export const $BackfillSnapshotsResponse = {
3409
+ type: 'object',
3410
+ properties: {}
3411
+ } as const;
3412
+
3413
+ export const $CreateBeanPriceDto = {
3414
+ type: 'object',
3415
+ properties: {
3416
+ currency: {
3417
+ type: 'string',
3418
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3419
+ example: 'USD'
3313
3420
  },
3314
- startDate: {
3421
+ quoteCurrency: {
3315
3422
  type: 'string',
3316
- description: 'Rule start date (ISO format)'
3423
+ description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
3424
+ example: 'CNY'
3317
3425
  },
3318
- endDate: {
3426
+ amount: {
3427
+ type: 'number',
3428
+ description:
3429
+ 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
3430
+ example: 175.5,
3431
+ minimum: 0
3432
+ },
3433
+ date: {
3319
3434
  type: 'string',
3320
- description: 'Rule end date (ISO format)'
3435
+ description: 'Price date (ISO 8601 format)',
3436
+ example: '2024-11-05'
3437
+ },
3438
+ metadata: {
3439
+ type: 'object',
3440
+ description:
3441
+ 'Metadata (validated by Zod schema, max field lengths enforced)',
3442
+ example: {
3443
+ source: 'MANUAL',
3444
+ note: 'Bank valuation report',
3445
+ confidence: 0.95
3446
+ }
3321
3447
  }
3322
3448
  },
3323
- required: [
3324
- 'name',
3325
- 'frequency',
3326
- 'expectedAmount',
3327
- 'currency',
3328
- 'matchAmountTolerance',
3329
- 'autoCreate'
3330
- ]
3449
+ required: ['currency', 'quoteCurrency', 'amount', 'date']
3331
3450
  } as const;
3332
3451
 
3333
- export const $RecurringRuleResponseDto = {
3452
+ export const $PriceResponseDto = {
3334
3453
  type: 'object',
3335
3454
  properties: {
3336
3455
  id: {
3337
3456
  type: 'string',
3338
- description: 'Rule ID'
3457
+ description: 'Unique identifier',
3458
+ example: 'uuid-123-456'
3339
3459
  },
3340
3460
  userId: {
3341
3461
  type: 'string',
3342
- description: 'User ID'
3462
+ description: 'User ID (owner of the price)',
3463
+ example: 'user-123'
3343
3464
  },
3344
- name: {
3465
+ currency: {
3345
3466
  type: 'string',
3346
- description: 'Rule name'
3347
- },
3348
- icon: {
3349
- type: 'object',
3350
- description: 'Icon emoji'
3467
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3468
+ example: 'BTC'
3351
3469
  },
3352
- frequency: {
3470
+ quoteCurrency: {
3353
3471
  type: 'string',
3354
- description: 'Recurring frequency'
3472
+ description: 'Quote currency (pricing currency, e.g., USD, CNY)',
3473
+ example: 'USD'
3355
3474
  },
3356
- expectedAmount: {
3475
+ amount: {
3357
3476
  type: 'number',
3358
- description: 'Expected amount'
3477
+ description:
3478
+ 'Price amount (corresponds to Beancount Amount.number). Supports up to 15 decimal places.',
3479
+ example: 50000
3359
3480
  },
3360
- expectedDay: {
3361
- type: 'object',
3362
- description: 'Expected day of month'
3481
+ date: {
3482
+ type: 'string',
3483
+ description:
3484
+ 'Price date (ISO 8601 format). Represents the date this price was valid.',
3485
+ example: '2024-01-01',
3486
+ format: 'date'
3363
3487
  },
3364
- customIntervalDays: {
3488
+ meta: {
3365
3489
  type: 'object',
3366
- description: 'Custom interval in days'
3490
+ description:
3491
+ 'Metadata (corresponds to Beancount meta field). Contains source, confidence, note, etc.',
3492
+ example: {
3493
+ source: 'MANUAL',
3494
+ note: 'User-defined price',
3495
+ confidence: 1
3496
+ }
3367
3497
  },
3368
- currency: {
3498
+ createdAt: {
3499
+ format: 'date-time',
3369
3500
  type: 'string',
3370
- description: 'Currency code'
3371
- },
3372
- matchPayeePattern: {
3373
- type: 'object',
3374
- description: 'Payee matching pattern'
3375
- },
3376
- matchAmountTolerance: {
3377
- type: 'number',
3378
- description: 'Amount tolerance percentage'
3379
- },
3380
- defaultExpenseAccount: {
3381
- type: 'object',
3382
- description: 'Default expense account'
3383
- },
3384
- defaultPaymentAccount: {
3385
- type: 'object',
3386
- description: 'Default payment account'
3387
- },
3388
- defaultPayee: {
3389
- type: 'object',
3390
- description: 'Default payee'
3391
- },
3392
- isActive: {
3393
- type: 'boolean',
3394
- description: 'Whether rule is active'
3395
- },
3396
- startDate: {
3397
- type: 'string',
3398
- description: 'Rule start date (YYYY-MM-DD)'
3399
- },
3400
- endDate: {
3401
- type: 'object',
3402
- description: 'Rule end date (YYYY-MM-DD)'
3403
- },
3404
- autoCreate: {
3405
- type: 'boolean',
3406
- description: 'Auto-create transaction on expected date'
3407
- },
3408
- lastOccurrence: {
3409
- type: 'object',
3410
- description: 'Last matched occurrence date (YYYY-MM-DD)'
3411
- },
3412
- totalCount: {
3413
- type: 'number',
3414
- description: 'Total matched transactions count'
3415
- },
3416
- createdAt: {
3417
- format: 'date-time',
3418
- type: 'string',
3419
- description: 'Created at timestamp'
3501
+ description: 'Creation timestamp',
3502
+ example: '2024-11-03T10:00:00Z'
3420
3503
  },
3421
3504
  updatedAt: {
3422
3505
  format: 'date-time',
3423
3506
  type: 'string',
3424
- description: 'Updated at timestamp'
3507
+ description: 'Last update timestamp',
3508
+ example: '2024-11-03T10:00:00Z'
3425
3509
  }
3426
3510
  },
3427
3511
  required: [
3428
3512
  'id',
3429
3513
  'userId',
3430
- 'name',
3431
- 'frequency',
3432
- 'expectedAmount',
3433
3514
  'currency',
3434
- 'matchAmountTolerance',
3435
- 'isActive',
3436
- 'startDate',
3437
- 'autoCreate',
3438
- 'totalCount',
3515
+ 'quoteCurrency',
3516
+ 'amount',
3517
+ 'date',
3518
+ 'meta',
3439
3519
  'createdAt',
3440
3520
  'updatedAt'
3441
3521
  ]
3442
3522
  } as const;
3443
3523
 
3444
- export const $CreateRuleFromTransactionDto = {
3524
+ export const $PriceListResponseDto = {
3445
3525
  type: 'object',
3446
3526
  properties: {
3447
- frequency: {
3527
+ items: {
3528
+ description: 'List of prices',
3529
+ type: 'array',
3530
+ items: {
3531
+ $ref: '#/components/schemas/PriceResponseDto'
3532
+ }
3533
+ },
3534
+ total: {
3535
+ type: 'number',
3536
+ description: 'Total number of prices',
3537
+ example: 42
3538
+ }
3539
+ },
3540
+ required: ['items', 'total']
3541
+ } as const;
3542
+
3543
+ export const $UpdateBeanPriceDto = {
3544
+ type: 'object',
3545
+ properties: {
3546
+ currency: {
3448
3547
  type: 'string',
3449
- description: 'Recurring frequency',
3450
- enum: [
3451
- 'WEEKLY',
3452
- 'BIWEEKLY',
3453
- 'MONTHLY',
3454
- 'BIMONTHLY',
3455
- 'QUARTERLY',
3456
- 'YEARLY',
3457
- 'CUSTOM'
3458
- ],
3459
- example: 'MONTHLY'
3548
+ description: 'Currency being priced'
3460
3549
  },
3461
- name: {
3550
+ quoteCurrency: {
3462
3551
  type: 'string',
3463
- description: 'Optional name override (default: transaction payee)',
3464
- maxLength: 100
3552
+ description: 'Quote currency (pricing currency)'
3465
3553
  },
3466
- icon: {
3554
+ amount: {
3555
+ type: 'number',
3556
+ description: 'Price amount (MUST be >= 0 per Beancount spec)',
3557
+ minimum: 0
3558
+ },
3559
+ date: {
3467
3560
  type: 'string',
3468
- description: 'Optional icon emoji',
3469
- maxLength: 10
3561
+ description: 'Price date (ISO 8601 format)'
3562
+ },
3563
+ metadata: {
3564
+ type: 'object',
3565
+ description: 'Metadata'
3566
+ }
3567
+ }
3568
+ } as const;
3569
+
3570
+ export const $DeleteOwnUserDto = {
3571
+ type: 'object',
3572
+ properties: {
3573
+ accessToken: {
3574
+ type: 'string',
3575
+ description: 'Access token for user verification',
3576
+ example: 'abc123xyz'
3470
3577
  }
3471
3578
  },
3472
- required: ['frequency']
3579
+ required: ['accessToken']
3473
3580
  } as const;
3474
3581
 
3475
- export const $RecurringRuleWithStatsResponseDto = {
3582
+ export const $UserSettingsResponseDto = {
3476
3583
  type: 'object',
3477
3584
  properties: {
3478
- id: {
3585
+ baseCurrency: {
3479
3586
  type: 'string',
3480
- description: 'Rule ID'
3481
- },
3482
- userId: {
3587
+ description:
3588
+ '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).',
3589
+ example: 'USD',
3590
+ nullable: true
3591
+ }
3592
+ },
3593
+ required: ['baseCurrency']
3594
+ } as const;
3595
+
3596
+ export const $UserResponseDto = {
3597
+ type: 'object',
3598
+ properties: {
3599
+ id: {
3483
3600
  type: 'string',
3484
3601
  description: 'User ID'
3485
3602
  },
3486
- name: {
3603
+ role: {
3487
3604
  type: 'string',
3488
- description: 'Rule name'
3605
+ description: 'Assigned user role'
3489
3606
  },
3490
- icon: {
3491
- type: 'object',
3492
- description: 'Icon emoji'
3607
+ permissions: {
3608
+ description: 'Permission strings',
3609
+ type: 'array',
3610
+ items: {
3611
+ type: 'string'
3612
+ }
3493
3613
  },
3494
- frequency: {
3614
+ settings: {
3615
+ description: 'User settings',
3616
+ allOf: [
3617
+ {
3618
+ $ref: '#/components/schemas/UserSettingsResponseDto'
3619
+ }
3620
+ ]
3621
+ }
3622
+ },
3623
+ required: ['id', 'role', 'permissions', 'settings']
3624
+ } as const;
3625
+
3626
+ export const $SignupDto = {
3627
+ type: 'object',
3628
+ properties: {
3629
+ turnstileToken: {
3495
3630
  type: 'string',
3496
- description: 'Recurring frequency'
3631
+ description:
3632
+ 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
3633
+ example: '0.abc123def456...'
3634
+ }
3635
+ }
3636
+ } as const;
3637
+
3638
+ export const $SignupResponseDto = {
3639
+ type: 'object',
3640
+ properties: {
3641
+ authToken: {
3642
+ type: 'string',
3643
+ description: 'JWT auth token',
3644
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
3497
3645
  },
3498
- expectedAmount: {
3499
- type: 'number',
3500
- description: 'Expected amount'
3646
+ accessToken: {
3647
+ type: 'string',
3648
+ description: 'Auto-generated access token'
3501
3649
  },
3502
- expectedDay: {
3503
- type: 'object',
3504
- description: 'Expected day of month'
3650
+ role: {
3651
+ type: 'string',
3652
+ description: 'Assigned user role',
3653
+ enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
3654
+ }
3655
+ },
3656
+ required: ['authToken', 'accessToken', 'role']
3657
+ } as const;
3658
+
3659
+ export const $UpdateUserSettingDto = {
3660
+ type: 'object',
3661
+ properties: {
3662
+ secId: {
3663
+ type: 'number',
3664
+ description: 'Security ID'
3505
3665
  },
3506
- customIntervalDays: {
3507
- type: 'object',
3508
- description: 'Custom interval in days'
3666
+ annualInterestRate: {
3667
+ type: 'number',
3668
+ description: 'Annual interest rate',
3669
+ example: 0.05
3509
3670
  },
3510
3671
  currency: {
3511
3672
  type: 'string',
3512
- description: 'Currency code'
3673
+ description: 'Currency code',
3674
+ example: 'USD'
3513
3675
  },
3514
- matchPayeePattern: {
3515
- type: 'object',
3516
- description: 'Payee matching pattern'
3676
+ baseCurrency: {
3677
+ type: 'string',
3678
+ description: 'Base currency code',
3679
+ example: 'USD'
3517
3680
  },
3518
- matchAmountTolerance: {
3519
- type: 'number',
3520
- description: 'Amount tolerance percentage'
3681
+ benchmark: {
3682
+ type: 'string',
3683
+ description: 'Benchmark symbol',
3684
+ example: 'SPY'
3521
3685
  },
3522
- defaultExpenseAccount: {
3523
- type: 'object',
3524
- description: 'Default expense account'
3686
+ colorScheme: {
3687
+ type: 'string',
3688
+ description: 'Color scheme',
3689
+ enum: ['DARK', 'LIGHT']
3525
3690
  },
3526
- defaultPaymentAccount: {
3527
- type: 'object',
3528
- description: 'Default payment account'
3691
+ dateRange: {
3692
+ type: 'string',
3693
+ description: 'Date range filter',
3694
+ example: '1y'
3529
3695
  },
3530
- defaultPayee: {
3531
- type: 'object',
3532
- description: 'Default payee'
3533
- },
3534
- isActive: {
3535
- type: 'boolean',
3536
- description: 'Whether rule is active'
3537
- },
3538
- startDate: {
3539
- type: 'string',
3540
- description: 'Rule start date (YYYY-MM-DD)'
3541
- },
3542
- endDate: {
3543
- type: 'object',
3544
- description: 'Rule end date (YYYY-MM-DD)'
3545
- },
3546
- autoCreate: {
3547
- type: 'boolean',
3548
- description: 'Auto-create transaction on expected date'
3696
+ emergencyFund: {
3697
+ type: 'number',
3698
+ description: 'Emergency fund amount',
3699
+ example: 10000
3549
3700
  },
3550
- lastOccurrence: {
3551
- type: 'object',
3552
- description: 'Last matched occurrence date (YYYY-MM-DD)'
3701
+ 'filters.accounts': {
3702
+ description: 'Account filter IDs',
3703
+ type: 'array',
3704
+ items: {
3705
+ type: 'string'
3706
+ }
3553
3707
  },
3554
- totalCount: {
3555
- type: 'number',
3556
- description: 'Total matched transactions count'
3708
+ 'filters.assetClasses': {
3709
+ description: 'Asset class filters',
3710
+ type: 'array',
3711
+ items: {
3712
+ type: 'string'
3713
+ }
3557
3714
  },
3558
- createdAt: {
3559
- format: 'date-time',
3715
+ 'filters.dataSource': {
3560
3716
  type: 'string',
3561
- description: 'Created at timestamp'
3717
+ description: 'Data source filter'
3562
3718
  },
3563
- updatedAt: {
3564
- format: 'date-time',
3719
+ 'filters.symbol': {
3565
3720
  type: 'string',
3566
- description: 'Updated at timestamp'
3721
+ description: 'Symbol filter'
3567
3722
  },
3568
- pendingCount: {
3569
- type: 'number',
3570
- description: 'Number of pending expected transactions'
3723
+ 'filters.tags': {
3724
+ description: 'Tag filters',
3725
+ type: 'array',
3726
+ items: {
3727
+ type: 'string'
3728
+ }
3571
3729
  },
3572
- overdueCount: {
3573
- type: 'number',
3574
- description: 'Number of overdue expected transactions'
3730
+ isExperimentalFeatures: {
3731
+ type: 'boolean',
3732
+ description: 'Enable experimental features'
3575
3733
  },
3576
- nextExpectedDate: {
3577
- type: 'object',
3578
- description: 'Next expected date (YYYY-MM-DD)'
3734
+ isRestrictedView: {
3735
+ type: 'boolean',
3736
+ description: 'Enable restricted view mode'
3579
3737
  },
3580
- totalAmount: {
3581
- type: 'number',
3582
- description: 'Total amount of all matched transactions'
3738
+ language: {
3739
+ type: 'string',
3740
+ description: 'Language code',
3741
+ example: 'en'
3583
3742
  },
3584
- averageAmount: {
3585
- type: 'number',
3586
- description: 'Average amount per transaction'
3743
+ locale: {
3744
+ type: 'string',
3745
+ description: 'Locale code',
3746
+ example: 'en-US'
3587
3747
  },
3588
- transactionCount: {
3748
+ projectedTotalAmount: {
3589
3749
  type: 'number',
3590
- description: 'Number of matched transactions'
3591
- },
3592
- firstDate: {
3593
- type: 'object',
3594
- description: 'First matched transaction date (YYYY-MM-DD)'
3750
+ description: 'Projected total amount',
3751
+ example: 1000000
3595
3752
  },
3596
- lastDate: {
3597
- type: 'object',
3598
- description: 'Last matched transaction date (YYYY-MM-DD)'
3753
+ retirementDate: {
3754
+ type: 'string',
3755
+ description: 'Retirement date in ISO 8601 format',
3756
+ example: '2050-01-01'
3599
3757
  },
3600
- variance: {
3758
+ savingsRate: {
3601
3759
  type: 'number',
3602
- description: 'Amount variance (standard deviation squared)'
3760
+ description: 'Savings rate percentage',
3761
+ example: 0.2
3603
3762
  },
3604
- upcomingCount: {
3605
- type: 'number',
3606
- description: 'Number of upcoming expected transactions'
3763
+ viewMode: {
3764
+ type: 'string',
3765
+ description: 'View mode',
3766
+ enum: ['DEFAULT', 'ZEN']
3767
+ }
3768
+ }
3769
+ } as const;
3770
+
3771
+ export const $UpdatePropertyDto = {
3772
+ type: 'object',
3773
+ properties: {
3774
+ value: {
3775
+ type: 'string',
3776
+ description: 'Property value'
3607
3777
  }
3608
3778
  },
3609
- required: [
3610
- 'id',
3611
- 'userId',
3612
- 'name',
3613
- 'frequency',
3614
- 'expectedAmount',
3615
- 'currency',
3616
- 'matchAmountTolerance',
3617
- 'isActive',
3618
- 'startDate',
3619
- 'autoCreate',
3620
- 'totalCount',
3621
- 'createdAt',
3622
- 'updatedAt',
3623
- 'pendingCount',
3624
- 'overdueCount',
3625
- 'totalAmount',
3626
- 'averageAmount',
3627
- 'transactionCount',
3628
- 'variance',
3629
- 'upcomingCount'
3630
- ]
3779
+ required: ['value']
3631
3780
  } as const;
3632
3781
 
3633
- export const $UpdateRecurringRuleDto = {
3782
+ export const $CreateRecurringRuleDto = {
3634
3783
  type: 'object',
3635
3784
  properties: {
3636
3785
  name: {
3637
3786
  type: 'string',
3638
- description: 'Rule name',
3787
+ description: 'Rule name (unique per user)',
3639
3788
  maxLength: 100
3640
3789
  },
3641
3790
  icon: {
@@ -3658,7 +3807,7 @@ export const $UpdateRecurringRuleDto = {
3658
3807
  },
3659
3808
  expectedAmount: {
3660
3809
  type: 'number',
3661
- description: 'Expected amount',
3810
+ description: 'Expected amount (positive number)',
3662
3811
  minimum: 0
3663
3812
  },
3664
3813
  expectedDay: {
@@ -3669,7 +3818,7 @@ export const $UpdateRecurringRuleDto = {
3669
3818
  },
3670
3819
  customIntervalDays: {
3671
3820
  type: 'number',
3672
- description: 'Custom interval in days',
3821
+ description: 'Custom interval in days (required for CUSTOM frequency)',
3673
3822
  minimum: 1
3674
3823
  },
3675
3824
  currency: {
@@ -3679,118 +3828,136 @@ export const $UpdateRecurringRuleDto = {
3679
3828
  },
3680
3829
  matchPayeePattern: {
3681
3830
  type: 'string',
3682
- description: 'Payee matching pattern',
3831
+ description: 'Payee matching pattern (supports wildcards)',
3683
3832
  maxLength: 200
3684
3833
  },
3685
3834
  matchAmountTolerance: {
3686
3835
  type: 'number',
3687
3836
  description: 'Amount tolerance percentage (0-1)',
3837
+ default: 0.075,
3688
3838
  minimum: 0,
3689
3839
  maximum: 1
3690
3840
  },
3691
3841
  defaultExpenseAccount: {
3692
3842
  type: 'string',
3693
- description: 'Default expense account',
3843
+ description: 'Default expense account for auto-create',
3694
3844
  maxLength: 200
3695
3845
  },
3696
3846
  defaultPaymentAccount: {
3697
3847
  type: 'string',
3698
- description: 'Default payment account',
3848
+ description: 'Default payment account for auto-create',
3699
3849
  maxLength: 200
3700
3850
  },
3701
3851
  defaultPayee: {
3702
3852
  type: 'string',
3703
- description: 'Default payee',
3853
+ description: 'Default payee for auto-create',
3704
3854
  maxLength: 200
3705
3855
  },
3706
3856
  autoCreate: {
3707
3857
  type: 'boolean',
3708
- description: 'Auto-create transaction'
3858
+ description: 'Auto-create transaction when expected date arrives',
3859
+ default: false
3709
3860
  },
3710
- isActive: {
3711
- type: 'boolean',
3712
- description: 'Rule active status'
3861
+ startDate: {
3862
+ type: 'string',
3863
+ description: 'Rule start date (ISO format)'
3713
3864
  },
3714
3865
  endDate: {
3715
3866
  type: 'string',
3716
3867
  description: 'Rule end date (ISO format)'
3717
3868
  }
3718
- }
3869
+ },
3870
+ required: [
3871
+ 'name',
3872
+ 'frequency',
3873
+ 'expectedAmount',
3874
+ 'matchAmountTolerance',
3875
+ 'autoCreate'
3876
+ ]
3719
3877
  } as const;
3720
3878
 
3721
- export const $ExpectedTransactionRuleDto = {
3879
+ export const $RecurringRuleResponseDto = {
3722
3880
  type: 'object',
3723
3881
  properties: {
3882
+ id: {
3883
+ type: 'string',
3884
+ description: 'Rule ID'
3885
+ },
3886
+ userId: {
3887
+ type: 'string',
3888
+ description: 'User ID'
3889
+ },
3724
3890
  name: {
3725
3891
  type: 'string',
3726
3892
  description: 'Rule name'
3727
3893
  },
3728
3894
  icon: {
3729
- type: 'object',
3730
- description: 'Rule icon'
3895
+ type: 'string',
3896
+ description: 'Icon emoji'
3731
3897
  },
3732
3898
  frequency: {
3733
3899
  type: 'string',
3734
- description: 'Rule frequency'
3900
+ description: 'Recurring frequency'
3901
+ },
3902
+ expectedAmount: {
3903
+ type: 'number',
3904
+ description: 'Expected amount'
3905
+ },
3906
+ expectedDay: {
3907
+ type: 'number',
3908
+ description: 'Expected day of month'
3909
+ },
3910
+ customIntervalDays: {
3911
+ type: 'number',
3912
+ description: 'Custom interval in days'
3735
3913
  },
3736
3914
  currency: {
3737
3915
  type: 'string',
3738
3916
  description: 'Currency code'
3739
- }
3740
- },
3741
- required: ['name', 'frequency', 'currency']
3742
- } as const;
3743
-
3744
- export const $ExpectedTransactionResponseDto = {
3745
- type: 'object',
3746
- properties: {
3747
- id: {
3917
+ },
3918
+ matchPayeePattern: {
3748
3919
  type: 'string',
3749
- description: 'Expected transaction ID'
3920
+ description: 'Payee matching pattern'
3750
3921
  },
3751
- userId: {
3922
+ matchAmountTolerance: {
3923
+ type: 'number',
3924
+ description: 'Amount tolerance percentage'
3925
+ },
3926
+ defaultExpenseAccount: {
3752
3927
  type: 'string',
3753
- description: 'User ID'
3928
+ description: 'Default expense account'
3754
3929
  },
3755
- ruleId: {
3930
+ defaultPaymentAccount: {
3756
3931
  type: 'string',
3757
- description: 'Associated rule ID'
3932
+ description: 'Default payment account'
3758
3933
  },
3759
- expectedDate: {
3934
+ defaultPayee: {
3760
3935
  type: 'string',
3761
- description: 'Expected date (YYYY-MM-DD)'
3936
+ description: 'Default payee'
3762
3937
  },
3763
- expectedAmount: {
3764
- type: 'number',
3765
- description: 'Expected amount'
3938
+ isActive: {
3939
+ type: 'boolean',
3940
+ description: 'Whether rule is active'
3766
3941
  },
3767
- status: {
3942
+ startDate: {
3768
3943
  type: 'string',
3769
- description: 'Status (PENDING, COMPLETED, SKIPPED)'
3944
+ description: 'Rule start date (YYYY-MM-DD)'
3770
3945
  },
3771
- matchedTransactionId: {
3772
- type: 'object',
3773
- description: 'Matched transaction ID'
3946
+ endDate: {
3947
+ type: 'string',
3948
+ description: 'Rule end date (YYYY-MM-DD)'
3774
3949
  },
3775
- matchedAt: {
3776
- type: 'object',
3777
- description: 'Match timestamp (ISO 8601)'
3950
+ autoCreate: {
3951
+ type: 'boolean',
3952
+ description: 'Auto-create transaction on expected date'
3778
3953
  },
3779
- matchConfidence: {
3780
- type: 'object',
3781
- description: 'Match confidence score (0-1)'
3782
- },
3783
- isOverdue: {
3784
- type: 'boolean',
3785
- description: 'Whether this expected transaction is overdue'
3954
+ lastOccurrence: {
3955
+ type: 'string',
3956
+ description: 'Last matched occurrence date (YYYY-MM-DD)'
3786
3957
  },
3787
- rule: {
3788
- description: 'Rule information',
3789
- allOf: [
3790
- {
3791
- $ref: '#/components/schemas/ExpectedTransactionRuleDto'
3792
- }
3793
- ]
3958
+ totalCount: {
3959
+ type: 'number',
3960
+ description: 'Total matched transactions count'
3794
3961
  },
3795
3962
  createdAt: {
3796
3963
  format: 'date-time',
@@ -3806,691 +3973,581 @@ export const $ExpectedTransactionResponseDto = {
3806
3973
  required: [
3807
3974
  'id',
3808
3975
  'userId',
3809
- 'ruleId',
3810
- 'expectedDate',
3976
+ 'name',
3977
+ 'frequency',
3811
3978
  'expectedAmount',
3812
- 'status',
3813
- 'isOverdue',
3814
- 'rule',
3979
+ 'currency',
3980
+ 'matchAmountTolerance',
3981
+ 'isActive',
3982
+ 'startDate',
3983
+ 'autoCreate',
3984
+ 'totalCount',
3815
3985
  'createdAt',
3816
3986
  'updatedAt'
3817
3987
  ]
3818
3988
  } as const;
3819
3989
 
3820
- export const $ExpectedTransactionListResponseDto = {
3990
+ export const $CreateRuleFromTransactionDto = {
3821
3991
  type: 'object',
3822
3992
  properties: {
3823
- items: {
3824
- type: 'array',
3825
- items: {
3826
- $ref: '#/components/schemas/ExpectedTransactionResponseDto'
3827
- }
3993
+ frequency: {
3994
+ type: 'string',
3995
+ description: 'Recurring frequency',
3996
+ enum: [
3997
+ 'WEEKLY',
3998
+ 'BIWEEKLY',
3999
+ 'MONTHLY',
4000
+ 'BIMONTHLY',
4001
+ 'QUARTERLY',
4002
+ 'YEARLY',
4003
+ 'CUSTOM'
4004
+ ],
4005
+ example: 'MONTHLY'
3828
4006
  },
3829
- total: {
3830
- type: 'number',
3831
- description: 'Total count'
3832
- }
3833
- },
3834
- required: ['items', 'total']
3835
- } as const;
3836
-
3837
- export const $ConfirmMatchDto = {
3838
- type: 'object',
3839
- properties: {
3840
- transactionId: {
4007
+ name: {
3841
4008
  type: 'string',
3842
- description: 'Transaction ID to match with'
4009
+ description: 'Optional name override (default: transaction payee)',
4010
+ maxLength: 100
4011
+ },
4012
+ icon: {
4013
+ type: 'string',
4014
+ description: 'Optional icon emoji',
4015
+ maxLength: 10
3843
4016
  }
3844
4017
  },
3845
- required: ['transactionId']
4018
+ required: ['frequency']
3846
4019
  } as const;
3847
4020
 
3848
- export const $EnterNowDto = {
4021
+ export const $RecurringRuleWithStatsResponseDto = {
3849
4022
  type: 'object',
3850
4023
  properties: {
3851
- expenseAccount: {
4024
+ id: {
3852
4025
  type: 'string',
3853
- description:
3854
- 'Override expense account (uses rule default if not provided)',
3855
- maxLength: 200
4026
+ description: 'Rule ID'
3856
4027
  },
3857
- paymentAccount: {
4028
+ userId: {
3858
4029
  type: 'string',
3859
- description:
3860
- 'Override payment account (uses rule default if not provided)',
3861
- maxLength: 200
4030
+ description: 'User ID'
3862
4031
  },
3863
- amount: {
3864
- type: 'number',
3865
- description: 'Override amount (uses expected amount if not provided)',
3866
- minimum: 0
4032
+ name: {
4033
+ type: 'string',
4034
+ description: 'Rule name'
3867
4035
  },
3868
- payee: {
4036
+ icon: {
3869
4037
  type: 'string',
3870
- description: 'Override payee (uses rule default if not provided)',
3871
- maxLength: 200
4038
+ description: 'Icon emoji'
3872
4039
  },
3873
- narration: {
4040
+ frequency: {
3874
4041
  type: 'string',
3875
- description: 'Optional narration',
3876
- maxLength: 500
3877
- }
3878
- }
3879
- } as const;
3880
-
3881
- export const $ForecastItemDto = {
3882
- type: 'object',
3883
- properties: {
3884
- rule: {
4042
+ description: 'Recurring frequency'
4043
+ },
4044
+ expectedAmount: {
4045
+ type: 'number',
4046
+ description: 'Expected amount'
4047
+ },
4048
+ expectedDay: {
4049
+ type: 'number',
4050
+ description: 'Expected day of month'
4051
+ },
4052
+ customIntervalDays: {
4053
+ type: 'number',
4054
+ description: 'Custom interval in days'
4055
+ },
4056
+ currency: {
3885
4057
  type: 'string',
3886
- description: 'Rule name',
3887
- example: 'Rent'
4058
+ description: 'Currency code'
3888
4059
  },
3889
- ruleId: {
4060
+ matchPayeePattern: {
3890
4061
  type: 'string',
3891
- description: 'Rule ID',
3892
- example: 'clx123...'
4062
+ description: 'Payee matching pattern'
3893
4063
  },
3894
- amount: {
4064
+ matchAmountTolerance: {
3895
4065
  type: 'number',
3896
- description: 'Expected amount',
3897
- example: 3000
4066
+ description: 'Amount tolerance percentage'
3898
4067
  },
3899
- date: {
4068
+ defaultExpenseAccount: {
3900
4069
  type: 'string',
3901
- description: 'Expected date (YYYY-MM-DD)',
3902
- example: '2024-04-01'
4070
+ description: 'Default expense account'
3903
4071
  },
3904
- icon: {
4072
+ defaultPaymentAccount: {
3905
4073
  type: 'string',
3906
- description: 'Rule icon emoji',
3907
- example: '🏠',
3908
- nullable: true
4074
+ description: 'Default payment account'
3909
4075
  },
3910
- currency: {
4076
+ defaultPayee: {
3911
4077
  type: 'string',
3912
- description: 'Currency code',
3913
- example: 'CNY'
3914
- }
3915
- },
3916
- required: ['rule', 'ruleId', 'amount', 'date', 'icon', 'currency']
3917
- } as const;
3918
-
3919
- export const $MonthlyForecastDto = {
3920
- type: 'object',
3921
- properties: {
3922
- month: {
4078
+ description: 'Default payee'
4079
+ },
4080
+ isActive: {
4081
+ type: 'boolean',
4082
+ description: 'Whether rule is active'
4083
+ },
4084
+ startDate: {
3923
4085
  type: 'string',
3924
- description: 'Month (YYYY-MM)',
3925
- example: '2024-04'
4086
+ description: 'Rule start date (YYYY-MM-DD)'
3926
4087
  },
3927
- expectedOutflow: {
3928
- type: 'number',
3929
- description: 'Total expected outflow for the month',
3930
- example: 8500
4088
+ endDate: {
4089
+ type: 'string',
4090
+ description: 'Rule end date (YYYY-MM-DD)'
3931
4091
  },
3932
- itemCount: {
4092
+ autoCreate: {
4093
+ type: 'boolean',
4094
+ description: 'Auto-create transaction on expected date'
4095
+ },
4096
+ lastOccurrence: {
4097
+ type: 'string',
4098
+ description: 'Last matched occurrence date (YYYY-MM-DD)'
4099
+ },
4100
+ totalCount: {
3933
4101
  type: 'number',
3934
- description: 'Number of expected transactions',
3935
- example: 3
4102
+ description: 'Total matched transactions count'
3936
4103
  },
3937
- byCurrency: {
3938
- type: 'object',
3939
- description: 'Breakdown by currency',
3940
- example: {
3941
- CNY: 8500,
3942
- USD: 100
3943
- }
4104
+ createdAt: {
4105
+ format: 'date-time',
4106
+ type: 'string',
4107
+ description: 'Created at timestamp'
3944
4108
  },
3945
- items: {
3946
- description: 'Individual forecast items',
3947
- type: 'array',
3948
- items: {
3949
- $ref: '#/components/schemas/ForecastItemDto'
3950
- }
3951
- }
3952
- },
3953
- required: ['month', 'expectedOutflow', 'itemCount', 'byCurrency', 'items']
3954
- } as const;
3955
-
3956
- export const $ForecastResponseDto = {
3957
- type: 'object',
3958
- properties: {
3959
- forecast: {
3960
- description: 'Monthly forecast data',
3961
- type: 'array',
3962
- items: {
3963
- $ref: '#/components/schemas/MonthlyForecastDto'
3964
- }
4109
+ updatedAt: {
4110
+ format: 'date-time',
4111
+ type: 'string',
4112
+ description: 'Updated at timestamp'
3965
4113
  },
3966
- totalOutflow: {
4114
+ pendingCount: {
3967
4115
  type: 'number',
3968
- description: 'Total expected outflow across all months',
3969
- example: 25500
3970
- },
3971
- totalByCurrency: {
3972
- type: 'object',
3973
- description: 'Total by currency across all months',
3974
- example: {
3975
- CNY: 25500,
3976
- USD: 300
3977
- }
4116
+ description: 'Number of pending expected transactions'
3978
4117
  },
3979
- rulesCount: {
4118
+ overdueCount: {
3980
4119
  type: 'number',
3981
- description: 'Number of active recurring rules included',
3982
- example: 5
4120
+ description: 'Number of overdue expected transactions'
3983
4121
  },
3984
- periodStart: {
4122
+ nextExpectedDate: {
3985
4123
  type: 'string',
3986
- description: 'Forecast period start date',
3987
- example: '2024-04-01'
4124
+ description: 'Next expected date (YYYY-MM-DD)'
3988
4125
  },
3989
- periodEnd: {
3990
- type: 'string',
3991
- description: 'Forecast period end date',
3992
- example: '2024-06-30'
3993
- }
3994
- },
3995
- required: [
3996
- 'forecast',
3997
- 'totalOutflow',
3998
- 'totalByCurrency',
3999
- 'rulesCount',
4000
- 'periodStart',
4001
- 'periodEnd'
4002
- ]
4003
- } as const;
4004
-
4005
- export const $CurrencyBalanceDto = {
4006
- type: 'object',
4007
- properties: {
4008
- currency: {
4009
- type: 'string',
4010
- description: 'ISO 4217 currency code',
4011
- example: 'CNY'
4012
- },
4013
- balance: {
4014
- type: 'string',
4015
- description: 'Balance amount',
4016
- example: '500000.00'
4017
- }
4018
- },
4019
- required: ['currency', 'balance']
4020
- } as const;
4021
-
4022
- export const $TimeSeriesPointDto = {
4023
- type: 'object',
4024
- properties: {
4025
- date: {
4026
- type: 'string',
4027
- description: 'Date in YYYY-MM-DD format',
4028
- example: '2024-06-15'
4126
+ totalAmount: {
4127
+ type: 'number',
4128
+ description: 'Total amount of all matched transactions'
4029
4129
  },
4030
- value: {
4031
- type: 'string',
4032
- description: 'Value at this date (in base currency)',
4033
- example: '500000.00'
4130
+ averageAmount: {
4131
+ type: 'number',
4132
+ description: 'Average amount per transaction'
4034
4133
  },
4035
- change: {
4036
- type: 'object',
4037
- description: 'Change from previous point',
4038
- example: '5000.00'
4134
+ transactionCount: {
4135
+ type: 'number',
4136
+ description: 'Number of matched transactions'
4039
4137
  },
4040
- assets: {
4138
+ firstDate: {
4041
4139
  type: 'string',
4042
- description: 'Total assets at this date (in base currency)',
4043
- example: '494338.00'
4140
+ description: 'First matched transaction date (YYYY-MM-DD)'
4044
4141
  },
4045
- liabilities: {
4142
+ lastDate: {
4046
4143
  type: 'string',
4047
- description: 'Total liabilities at this date (in base currency)',
4048
- example: '310098.00'
4144
+ description: 'Last matched transaction date (YYYY-MM-DD)'
4049
4145
  },
4050
- byCurrency: {
4051
- description: 'Multi-currency breakdown for this point',
4052
- type: 'array',
4053
- items: {
4054
- $ref: '#/components/schemas/CurrencyBalanceDto'
4055
- }
4146
+ variance: {
4147
+ type: 'number',
4148
+ description: 'Amount variance (standard deviation squared)'
4149
+ },
4150
+ upcomingCount: {
4151
+ type: 'number',
4152
+ description: 'Number of upcoming expected transactions'
4056
4153
  }
4057
4154
  },
4058
- required: ['date', 'value']
4155
+ required: [
4156
+ 'id',
4157
+ 'userId',
4158
+ 'name',
4159
+ 'frequency',
4160
+ 'expectedAmount',
4161
+ 'currency',
4162
+ 'matchAmountTolerance',
4163
+ 'isActive',
4164
+ 'startDate',
4165
+ 'autoCreate',
4166
+ 'totalCount',
4167
+ 'createdAt',
4168
+ 'updatedAt',
4169
+ 'pendingCount',
4170
+ 'overdueCount',
4171
+ 'totalAmount',
4172
+ 'averageAmount',
4173
+ 'transactionCount',
4174
+ 'variance',
4175
+ 'upcomingCount'
4176
+ ]
4059
4177
  } as const;
4060
4178
 
4061
- export const $TrendSummaryDto = {
4179
+ export const $UpdateRecurringRuleDto = {
4062
4180
  type: 'object',
4063
4181
  properties: {
4064
- startValue: {
4065
- type: 'string',
4066
- description: 'Value at start of period',
4067
- example: '450000.00'
4068
- },
4069
- endValue: {
4182
+ name: {
4070
4183
  type: 'string',
4071
- description: 'Value at end of period',
4072
- example: '500000.00'
4184
+ description: 'Rule name (unique per user)',
4185
+ maxLength: 100
4073
4186
  },
4074
- totalChange: {
4187
+ icon: {
4075
4188
  type: 'string',
4076
- description: 'Total change over period',
4077
- example: '50000.00'
4189
+ description: 'Icon emoji',
4190
+ maxLength: 10
4078
4191
  },
4079
- totalChangePercentage: {
4080
- type: 'string',
4081
- description: 'Total change percentage',
4082
- example: '+11.11%'
4083
- }
4084
- },
4085
- required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
4086
- } as const;
4087
-
4088
- export const $MultiCurrencyPointDto = {
4089
- type: 'object',
4090
- properties: {
4091
- date: {
4192
+ frequency: {
4092
4193
  type: 'string',
4093
- description: 'Date in YYYY-MM-DD format',
4094
- example: '2024-06-15'
4095
- },
4096
- byCurrency: {
4097
- description: 'Balances by currency',
4098
- type: 'array',
4099
- items: {
4100
- $ref: '#/components/schemas/CurrencyBalanceDto'
4101
- }
4102
- }
4103
- },
4104
- required: ['date', 'byCurrency']
4105
- } as const;
4106
-
4107
- export const $PortfolioTrendsResponseDto = {
4108
- type: 'object',
4109
- properties: {
4110
- series: {
4111
- description: 'Time series data points',
4112
- type: 'array',
4113
- items: {
4114
- $ref: '#/components/schemas/TimeSeriesPointDto'
4115
- }
4116
- },
4117
- summary: {
4118
- description: 'Period summary',
4119
- allOf: [
4120
- {
4121
- $ref: '#/components/schemas/TrendSummaryDto'
4122
- }
4194
+ description: 'Recurring frequency',
4195
+ enum: [
4196
+ 'WEEKLY',
4197
+ 'BIWEEKLY',
4198
+ 'MONTHLY',
4199
+ 'BIMONTHLY',
4200
+ 'QUARTERLY',
4201
+ 'YEARLY',
4202
+ 'CUSTOM'
4123
4203
  ]
4124
4204
  },
4125
- period: {
4126
- type: 'string',
4127
- description: 'Period requested',
4128
- example: '6m'
4205
+ expectedAmount: {
4206
+ type: 'number',
4207
+ description: 'Expected amount (positive number)',
4208
+ minimum: 0
4129
4209
  },
4130
- granularity: {
4131
- type: 'string',
4132
- description: 'Data granularity',
4133
- example: 'month'
4210
+ expectedDay: {
4211
+ type: 'number',
4212
+ description: 'Expected day of month (1-31)',
4213
+ minimum: 1,
4214
+ maximum: 31
4134
4215
  },
4135
4216
  currency: {
4136
4217
  type: 'string',
4137
- description: 'Base currency for converted values',
4138
- example: 'CNY'
4139
- },
4140
- byCurrency: {
4141
- description:
4142
- 'Multi-currency time series (each point has currency breakdown)',
4143
- type: 'array',
4144
- items: {
4145
- $ref: '#/components/schemas/MultiCurrencyPointDto'
4146
- }
4147
- },
4148
- warnings: {
4149
- description: 'Exchange rate warnings',
4150
- type: 'array',
4151
- items: {
4152
- $ref: '#/components/schemas/ExchangeRateWarningDto'
4153
- }
4154
- }
4155
- },
4156
- required: ['series', 'summary', 'period', 'granularity', 'currency']
4157
- } as const;
4158
-
4159
- export const $CashFlowPointDto = {
4160
- type: 'object',
4161
- properties: {
4162
- month: {
4163
- type: 'string',
4164
- description: 'Month key (YYYY-MM)',
4165
- example: '2024-03'
4166
- },
4167
- income: {
4168
- type: 'string',
4169
- description: 'Income in base currency (absolute, converted)',
4170
- example: '10000.00'
4218
+ description: 'Currency code',
4219
+ maxLength: 10
4171
4220
  },
4172
- expense: {
4221
+ matchPayeePattern: {
4173
4222
  type: 'string',
4174
- description: 'Expense in base currency (absolute, converted)',
4175
- example: '5000.00'
4223
+ description: 'Payee matching pattern (supports wildcards)',
4224
+ maxLength: 200
4176
4225
  },
4177
- netSavings: {
4178
- type: 'string',
4179
- description: 'netSavings = income − expense (savings positive)',
4180
- example: '5000.00'
4181
- }
4182
- },
4183
- required: ['month', 'income', 'expense', 'netSavings']
4184
- } as const;
4185
-
4186
- export const $CashFlowTrendSummaryDto = {
4187
- type: 'object',
4188
- properties: {
4189
- totalIncome: {
4190
- type: 'string',
4191
- description: 'Total income across the period',
4192
- example: '60000.00'
4226
+ matchAmountTolerance: {
4227
+ type: 'number',
4228
+ description: 'Amount tolerance percentage (0-1)',
4229
+ default: 0.075,
4230
+ minimum: 0,
4231
+ maximum: 1
4193
4232
  },
4194
- totalExpense: {
4233
+ defaultExpenseAccount: {
4195
4234
  type: 'string',
4196
- description: 'Total expense across the period',
4197
- example: '30000.00'
4235
+ description: 'Default expense account for auto-create',
4236
+ maxLength: 200
4198
4237
  },
4199
- totalNetSavings: {
4238
+ defaultPaymentAccount: {
4200
4239
  type: 'string',
4201
- description: 'income − expense across the period',
4202
- example: '30000.00'
4240
+ description: 'Default payment account for auto-create',
4241
+ maxLength: 200
4203
4242
  },
4204
- averageMonthlyNetSavings: {
4243
+ defaultPayee: {
4205
4244
  type: 'string',
4206
- description:
4207
- 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
4208
- example: '5000.00'
4209
- }
4210
- },
4211
- required: [
4212
- 'totalIncome',
4213
- 'totalExpense',
4214
- 'totalNetSavings',
4215
- 'averageMonthlyNetSavings'
4216
- ]
4217
- } as const;
4218
-
4219
- export const $CashFlowTrendsResponseDto = {
4220
- type: 'object',
4221
- properties: {
4222
- series: {
4223
- description:
4224
- 'Monthly cash-flow series (fixed N-month window, zero-filled)',
4225
- type: 'array',
4226
- items: {
4227
- $ref: '#/components/schemas/CashFlowPointDto'
4228
- }
4229
- },
4230
- summary: {
4231
- description: 'Period totals',
4232
- allOf: [
4233
- {
4234
- $ref: '#/components/schemas/CashFlowTrendSummaryDto'
4235
- }
4236
- ]
4245
+ description: 'Default payee for auto-create',
4246
+ maxLength: 200
4237
4247
  },
4238
- period: {
4239
- type: 'string',
4240
- description: 'Period requested',
4241
- example: '6m'
4248
+ autoCreate: {
4249
+ type: 'boolean',
4250
+ description: 'Auto-create transaction when expected date arrives',
4251
+ default: false
4242
4252
  },
4243
- granularity: {
4253
+ endDate: {
4244
4254
  type: 'string',
4245
- description: 'Data granularity (v1 returns month buckets)',
4246
- example: 'month'
4255
+ description: 'Rule end date (ISO format)'
4247
4256
  },
4248
- currency: {
4249
- type: 'string',
4250
- description: 'Base currency for converted values',
4251
- example: 'CNY'
4257
+ customIntervalDays: {
4258
+ type: 'number',
4259
+ description: 'Custom interval in days',
4260
+ minimum: 1
4252
4261
  },
4253
- warnings: {
4254
- description: 'Exchange rate warnings (e.g. missing rate for a currency)',
4255
- type: 'array',
4256
- items: {
4257
- $ref: '#/components/schemas/ExchangeRateWarningDto'
4258
- }
4259
- }
4260
- },
4261
- required: ['series', 'summary', 'period', 'granularity', 'currency']
4262
- } as const;
4263
-
4264
- export const $GenerateSnapshotBody = {
4265
- type: 'object',
4266
- properties: {}
4267
- } as const;
4268
-
4269
- export const $GenerateSnapshotResponse = {
4270
- type: 'object',
4271
- properties: {}
4272
- } as const;
4273
-
4274
- export const $BackfillSnapshotsBody = {
4275
- type: 'object',
4276
- properties: {}
4277
- } as const;
4278
-
4279
- export const $BackfillSnapshotsResponse = {
4280
- type: 'object',
4281
- properties: {}
4282
- } as const;
4283
-
4284
- export const $DeleteOwnUserDto = {
4285
- type: 'object',
4286
- properties: {
4287
- accessToken: {
4288
- type: 'string',
4289
- description: 'Access token for user verification',
4290
- example: 'abc123xyz'
4262
+ isActive: {
4263
+ type: 'boolean',
4264
+ description: 'Rule active status'
4291
4265
  }
4292
- },
4293
- required: ['accessToken']
4266
+ }
4294
4267
  } as const;
4295
4268
 
4296
- export const $UserSettingsResponseDto = {
4269
+ export const $ExpectedTransactionRuleDto = {
4297
4270
  type: 'object',
4298
4271
  properties: {
4299
- baseCurrency: {
4272
+ name: {
4300
4273
  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
4274
+ description: 'Rule name'
4275
+ },
4276
+ icon: {
4277
+ type: 'string',
4278
+ description: 'Rule icon'
4279
+ },
4280
+ frequency: {
4281
+ type: 'string',
4282
+ description: 'Rule frequency'
4283
+ },
4284
+ currency: {
4285
+ type: 'string',
4286
+ description: 'Currency code'
4305
4287
  }
4306
4288
  },
4307
- required: ['baseCurrency']
4289
+ required: ['name', 'frequency', 'currency']
4308
4290
  } as const;
4309
4291
 
4310
- export const $UserResponseDto = {
4292
+ export const $ExpectedTransactionResponseDto = {
4311
4293
  type: 'object',
4312
4294
  properties: {
4313
4295
  id: {
4296
+ type: 'string',
4297
+ description: 'Expected transaction ID'
4298
+ },
4299
+ userId: {
4314
4300
  type: 'string',
4315
4301
  description: 'User ID'
4316
4302
  },
4317
- role: {
4303
+ ruleId: {
4318
4304
  type: 'string',
4319
- description: 'Assigned user role'
4305
+ description: 'Associated rule ID'
4320
4306
  },
4321
- permissions: {
4322
- description: 'Permission strings',
4323
- type: 'array',
4324
- items: {
4325
- type: 'string'
4326
- }
4307
+ expectedDate: {
4308
+ type: 'string',
4309
+ description: 'Expected date (YYYY-MM-DD)'
4327
4310
  },
4328
- settings: {
4329
- description: 'User settings',
4311
+ expectedAmount: {
4312
+ type: 'number',
4313
+ description: 'Expected amount'
4314
+ },
4315
+ status: {
4316
+ type: 'string',
4317
+ description: 'Status (PENDING, COMPLETED, SKIPPED)'
4318
+ },
4319
+ matchedTransactionId: {
4320
+ type: 'string',
4321
+ description: 'Matched transaction ID'
4322
+ },
4323
+ matchedAt: {
4324
+ type: 'string',
4325
+ description: 'Match timestamp (ISO 8601)'
4326
+ },
4327
+ matchConfidence: {
4328
+ type: 'number',
4329
+ description: 'Match confidence score (0-1)'
4330
+ },
4331
+ isOverdue: {
4332
+ type: 'boolean',
4333
+ description: 'Whether this expected transaction is overdue'
4334
+ },
4335
+ rule: {
4336
+ description: 'Rule information',
4330
4337
  allOf: [
4331
4338
  {
4332
- $ref: '#/components/schemas/UserSettingsResponseDto'
4339
+ $ref: '#/components/schemas/ExpectedTransactionRuleDto'
4333
4340
  }
4334
4341
  ]
4342
+ },
4343
+ createdAt: {
4344
+ format: 'date-time',
4345
+ type: 'string',
4346
+ description: 'Created at timestamp'
4347
+ },
4348
+ updatedAt: {
4349
+ format: 'date-time',
4350
+ type: 'string',
4351
+ description: 'Updated at timestamp'
4335
4352
  }
4336
4353
  },
4337
- required: ['id', 'role', 'permissions', 'settings']
4354
+ required: [
4355
+ 'id',
4356
+ 'userId',
4357
+ 'ruleId',
4358
+ 'expectedDate',
4359
+ 'expectedAmount',
4360
+ 'status',
4361
+ 'isOverdue',
4362
+ 'rule',
4363
+ 'createdAt',
4364
+ 'updatedAt'
4365
+ ]
4338
4366
  } as const;
4339
4367
 
4340
- export const $SignupDto = {
4368
+ export const $ExpectedTransactionListResponseDto = {
4341
4369
  type: 'object',
4342
4370
  properties: {
4343
- turnstileToken: {
4371
+ items: {
4372
+ type: 'array',
4373
+ items: {
4374
+ $ref: '#/components/schemas/ExpectedTransactionResponseDto'
4375
+ }
4376
+ },
4377
+ total: {
4378
+ type: 'number',
4379
+ description: 'Total count'
4380
+ }
4381
+ },
4382
+ required: ['items', 'total']
4383
+ } as const;
4384
+
4385
+ export const $ConfirmMatchDto = {
4386
+ type: 'object',
4387
+ properties: {
4388
+ transactionId: {
4344
4389
  type: 'string',
4345
- description:
4346
- 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4347
- example: '0.abc123def456...'
4390
+ description: 'Transaction ID to match with'
4348
4391
  }
4349
- }
4392
+ },
4393
+ required: ['transactionId']
4350
4394
  } as const;
4351
4395
 
4352
- export const $SignupResponseDto = {
4396
+ export const $EnterNowDto = {
4353
4397
  type: 'object',
4354
4398
  properties: {
4355
- authToken: {
4399
+ expenseAccount: {
4356
4400
  type: 'string',
4357
- description: 'JWT auth token',
4358
- example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
4401
+ description:
4402
+ 'Override expense account (uses rule default if not provided)',
4403
+ maxLength: 200
4359
4404
  },
4360
- accessToken: {
4405
+ paymentAccount: {
4361
4406
  type: 'string',
4362
- description: 'Auto-generated access token'
4407
+ description:
4408
+ 'Override payment account (uses rule default if not provided)',
4409
+ maxLength: 200
4363
4410
  },
4364
- role: {
4411
+ amount: {
4412
+ type: 'number',
4413
+ description: 'Override amount (uses expected amount if not provided)',
4414
+ minimum: 0
4415
+ },
4416
+ payee: {
4365
4417
  type: 'string',
4366
- description: 'Assigned user role',
4367
- enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
4418
+ description: 'Override payee (uses rule default if not provided)',
4419
+ maxLength: 200
4420
+ },
4421
+ narration: {
4422
+ type: 'string',
4423
+ description: 'Optional narration',
4424
+ maxLength: 500
4368
4425
  }
4369
- },
4370
- required: ['authToken', 'accessToken', 'role']
4426
+ }
4371
4427
  } as const;
4372
4428
 
4373
- export const $UpdateUserSettingDto = {
4429
+ export const $ForecastItemDto = {
4374
4430
  type: 'object',
4375
4431
  properties: {
4376
- secId: {
4377
- type: 'number',
4378
- description: 'Security ID'
4432
+ rule: {
4433
+ type: 'string',
4434
+ description: 'Rule name',
4435
+ example: 'Rent'
4379
4436
  },
4380
- annualInterestRate: {
4437
+ ruleId: {
4438
+ type: 'string',
4439
+ description: 'Rule ID',
4440
+ example: 'clx123...'
4441
+ },
4442
+ amount: {
4381
4443
  type: 'number',
4382
- description: 'Annual interest rate',
4383
- example: 0.05
4444
+ description: 'Expected amount',
4445
+ example: 3000
4384
4446
  },
4385
- currency: {
4447
+ date: {
4386
4448
  type: 'string',
4387
- description: 'Currency code',
4388
- example: 'USD'
4449
+ description: 'Expected date (YYYY-MM-DD)',
4450
+ example: '2024-04-01'
4389
4451
  },
4390
- baseCurrency: {
4452
+ icon: {
4391
4453
  type: 'string',
4392
- description: 'Base currency code',
4393
- example: 'USD'
4454
+ description: 'Rule icon emoji',
4455
+ example: '🏠',
4456
+ nullable: true
4394
4457
  },
4395
- benchmark: {
4458
+ currency: {
4396
4459
  type: 'string',
4397
- description: 'Benchmark symbol',
4398
- example: 'SPY'
4399
- },
4400
- colorScheme: {
4460
+ description: 'Currency code',
4461
+ example: 'CNY'
4462
+ }
4463
+ },
4464
+ required: ['rule', 'ruleId', 'amount', 'date', 'icon', 'currency']
4465
+ } as const;
4466
+
4467
+ export const $MonthlyForecastDto = {
4468
+ type: 'object',
4469
+ properties: {
4470
+ month: {
4401
4471
  type: 'string',
4402
- description: 'Color scheme',
4403
- enum: ['DARK', 'LIGHT']
4472
+ description: 'Month (YYYY-MM)',
4473
+ example: '2024-04'
4404
4474
  },
4405
- dateRange: {
4406
- type: 'string',
4407
- description: 'Date range filter',
4408
- example: '1y'
4475
+ expectedOutflow: {
4476
+ type: 'number',
4477
+ description: 'Total expected outflow for the month',
4478
+ example: 8500
4409
4479
  },
4410
- emergencyFund: {
4480
+ itemCount: {
4411
4481
  type: 'number',
4412
- description: 'Emergency fund amount',
4413
- example: 10000
4482
+ description: 'Number of expected transactions',
4483
+ example: 3
4414
4484
  },
4415
- 'filters.accounts': {
4416
- description: 'Account filter IDs',
4417
- type: 'array',
4418
- items: {
4419
- type: 'string'
4485
+ byCurrency: {
4486
+ type: 'object',
4487
+ description: 'Breakdown by currency',
4488
+ example: {
4489
+ CNY: 8500,
4490
+ USD: 100
4420
4491
  }
4421
4492
  },
4422
- 'filters.assetClasses': {
4423
- description: 'Asset class filters',
4493
+ items: {
4494
+ description: 'Individual forecast items',
4424
4495
  type: 'array',
4425
4496
  items: {
4426
- type: 'string'
4427
- }
4428
- },
4429
- 'filters.dataSource': {
4430
- type: 'string',
4431
- description: 'Data source filter'
4432
- },
4433
- 'filters.symbol': {
4434
- type: 'string',
4435
- description: 'Symbol filter'
4436
- },
4437
- 'filters.tags': {
4438
- description: 'Tag filters',
4497
+ $ref: '#/components/schemas/ForecastItemDto'
4498
+ }
4499
+ }
4500
+ },
4501
+ required: ['month', 'expectedOutflow', 'itemCount', 'byCurrency', 'items']
4502
+ } as const;
4503
+
4504
+ export const $ForecastResponseDto = {
4505
+ type: 'object',
4506
+ properties: {
4507
+ forecast: {
4508
+ description: 'Monthly forecast data',
4439
4509
  type: 'array',
4440
4510
  items: {
4441
- type: 'string'
4511
+ $ref: '#/components/schemas/MonthlyForecastDto'
4442
4512
  }
4443
4513
  },
4444
- isExperimentalFeatures: {
4445
- type: 'boolean',
4446
- description: 'Enable experimental features'
4447
- },
4448
- isRestrictedView: {
4449
- type: 'boolean',
4450
- description: 'Enable restricted view mode'
4451
- },
4452
- language: {
4453
- type: 'string',
4454
- description: 'Language code',
4455
- example: 'en'
4456
- },
4457
- locale: {
4458
- type: 'string',
4459
- description: 'Locale code',
4460
- example: 'en-US'
4461
- },
4462
- projectedTotalAmount: {
4514
+ totalOutflow: {
4463
4515
  type: 'number',
4464
- description: 'Projected total amount',
4465
- example: 1000000
4516
+ description: 'Total expected outflow across all months',
4517
+ example: 25500
4466
4518
  },
4467
- retirementDate: {
4468
- type: 'string',
4469
- description: 'Retirement date in ISO 8601 format',
4470
- example: '2050-01-01'
4519
+ totalByCurrency: {
4520
+ type: 'object',
4521
+ description: 'Total by currency across all months',
4522
+ example: {
4523
+ CNY: 25500,
4524
+ USD: 300
4525
+ }
4471
4526
  },
4472
- savingsRate: {
4527
+ rulesCount: {
4473
4528
  type: 'number',
4474
- description: 'Savings rate percentage',
4475
- example: 0.2
4529
+ description: 'Number of active recurring rules included',
4530
+ example: 5
4476
4531
  },
4477
- viewMode: {
4532
+ periodStart: {
4478
4533
  type: 'string',
4479
- description: 'View mode',
4480
- enum: ['DEFAULT', 'ZEN']
4481
- }
4482
- }
4483
- } as const;
4484
-
4485
- export const $UpdatePropertyDto = {
4486
- type: 'object',
4487
- properties: {
4488
- value: {
4534
+ description: 'Forecast period start date',
4535
+ example: '2024-04-01'
4536
+ },
4537
+ periodEnd: {
4489
4538
  type: 'string',
4490
- description: 'Property value'
4539
+ description: 'Forecast period end date',
4540
+ example: '2024-06-30'
4491
4541
  }
4492
4542
  },
4493
- required: ['value']
4543
+ required: [
4544
+ 'forecast',
4545
+ 'totalOutflow',
4546
+ 'totalByCurrency',
4547
+ 'rulesCount',
4548
+ 'periodStart',
4549
+ 'periodEnd'
4550
+ ]
4494
4551
  } as const;
4495
4552
 
4496
4553
  export const $CreateTransactionRuleDto = {
@@ -5052,7 +5109,8 @@ export const $UpdateTransactionRuleDto = {
5052
5109
  },
5053
5110
  matchLogic: {
5054
5111
  type: 'string',
5055
- enum: ['OR', 'AND']
5112
+ enum: ['OR', 'AND'],
5113
+ default: 'OR'
5056
5114
  },
5057
5115
  amountMin: {
5058
5116
  type: 'number',
@@ -5066,13 +5124,10 @@ export const $UpdateTransactionRuleDto = {
5066
5124
  },
5067
5125
  priority: {
5068
5126
  type: 'number',
5127
+ default: 50,
5069
5128
  minimum: 0,
5070
5129
  maximum: 1000
5071
5130
  },
5072
- enabled: {
5073
- type: 'boolean',
5074
- description: 'Enable or disable the rule'
5075
- },
5076
5131
  additionalTags: {
5077
5132
  items: {
5078
5133
  type: 'array'
@@ -5082,6 +5137,10 @@ export const $UpdateTransactionRuleDto = {
5082
5137
  },
5083
5138
  additionalMetadata: {
5084
5139
  type: 'object'
5140
+ },
5141
+ enabled: {
5142
+ type: 'boolean',
5143
+ description: 'Enable or disable the rule'
5085
5144
  }
5086
5145
  }
5087
5146
  } as const;
@@ -5175,9 +5234,23 @@ export const $CategoryCatalogEntryDto = {
5175
5234
  items: {
5176
5235
  type: 'string'
5177
5236
  }
5237
+ },
5238
+ categoryAccounts: {
5239
+ description:
5240
+ "Beancount account paths (categoryAccount) of the region-enabled system rules whose categoryKeywords include this slug (#816). System rules only (public endpoint — user rules excluded); one-to-many by design (e.g. 'utilities' → Electricity/Water/Internet/Gas), sorted, [] when no rule maps the slug.",
5241
+ example: [
5242
+ 'Expenses:Utilities:Electricity',
5243
+ 'Expenses:Utilities:Gas',
5244
+ 'Expenses:Utilities:Internet',
5245
+ 'Expenses:Utilities:Water'
5246
+ ],
5247
+ type: 'array',
5248
+ items: {
5249
+ type: 'string'
5250
+ }
5178
5251
  }
5179
5252
  },
5180
- required: ['slug', 'scenario', 'icon', 'regions']
5253
+ required: ['slug', 'scenario', 'icon', 'regions', 'categoryAccounts']
5181
5254
  } as const;
5182
5255
 
5183
5256
  export const $CategoryCatalogListResponseDto = {
@@ -5368,6 +5441,14 @@ export const $OnboardingAccountDto = {
5368
5441
  description:
5369
5442
  'Platform ID to bind the account to (references Platform.id); omit for unbound',
5370
5443
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
5444
+ },
5445
+ displayName: {
5446
+ type: 'string',
5447
+ description:
5448
+ 'User-set display name override (omit/null = keep the derived name)',
5449
+ nullable: true,
5450
+ maxLength: 50,
5451
+ example: 'Salary card'
5371
5452
  }
5372
5453
  },
5373
5454
  required: ['path', 'currency']
@@ -6288,8 +6369,9 @@ export const $ClientParsedDataDto = {
6288
6369
  },
6289
6370
  category: {
6290
6371
  type: 'string',
6291
- description: 'Category slug',
6292
- example: 'food_restaurant'
6372
+ description:
6373
+ 'Category in canonical form (catalog slug or Stage-2 rule keyword token, ADR-0116) — echo back verbatim from parsedData.category. Foreign forms (locale display names, account paths) are rejected with nlp.category.invalid.',
6374
+ example: 'food'
6293
6375
  },
6294
6376
  incomeType: {
6295
6377
  type: 'string',
@@ -6389,6 +6471,25 @@ export const $ProcessNlpDto = {
6389
6471
  description:
6390
6472
  'confirm_account echo-back: account path selected from the prior confirm_account response (suggestedAccount, similarAccounts[i].path, or a typed path). Applied directly when the session is confirming_account — no NL re-parse.',
6391
6473
  example: 'Expenses:Food:Coffee'
6474
+ },
6475
+ viewpointAccount: {
6476
+ type: 'string',
6477
+ description:
6478
+ '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.',
6479
+ example: 'Assets:CN:Bank:ICBC'
6480
+ },
6481
+ viewpointCategory: {
6482
+ type: 'string',
6483
+ description:
6484
+ "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.",
6485
+ example: 'Food'
6486
+ },
6487
+ viewpointFlow: {
6488
+ type: 'string',
6489
+ description:
6490
+ "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.",
6491
+ enum: ['income', 'expense'],
6492
+ example: 'expense'
6392
6493
  }
6393
6494
  }
6394
6495
  } as const;
@@ -6456,7 +6557,9 @@ export const $NlpParsedDataDto = {
6456
6557
  },
6457
6558
  category: {
6458
6559
  type: 'string',
6459
- description: 'Category'
6560
+ description:
6561
+ 'Category in canonical form: a CATEGORY_CATALOG slug (GET /{region}/bean/categories) or a Stage-2 rule categoryKeywords token (ADR-0116 D2). Never a locale display name or a beancount account path. Echo back verbatim on confirm.',
6562
+ example: 'food'
6460
6563
  },
6461
6564
  incomeType: {
6462
6565
  type: 'string',
@@ -7367,6 +7470,79 @@ export const $PlatformMatchResponseDto = {
7367
7470
  required: ['platforms', 'matchType', 'total', 'hasMore']
7368
7471
  } as const;
7369
7472
 
7473
+ export const $PlatformStandardsPlatformDto = {
7474
+ type: 'object',
7475
+ properties: {
7476
+ id: {
7477
+ type: 'string',
7478
+ description: 'Global platform ID'
7479
+ },
7480
+ name: {
7481
+ type: 'string',
7482
+ description: 'Platform name (e.g., "ICBC")'
7483
+ },
7484
+ canonical: {
7485
+ type: 'string',
7486
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7487
+ },
7488
+ suggestedSegment: {
7489
+ type: 'string',
7490
+ description:
7491
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7492
+ },
7493
+ type: {
7494
+ type: 'string',
7495
+ description: 'Platform type',
7496
+ enum: [
7497
+ 'BANK',
7498
+ 'BROKERAGE',
7499
+ 'CRYPTO_EXCHANGE',
7500
+ 'PAYMENT',
7501
+ 'INVESTMENT',
7502
+ 'INSURANCE',
7503
+ 'OTHER'
7504
+ ]
7505
+ },
7506
+ category: {
7507
+ type: 'string',
7508
+ description:
7509
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank) resolved against the final region. null = no region-aware suggestion; fall back to type.',
7510
+ nullable: true,
7511
+ example: 'Bank'
7512
+ }
7513
+ },
7514
+ required: ['id', 'name', 'canonical', 'suggestedSegment', 'type', 'category']
7515
+ } as const;
7516
+
7517
+ export const $PlatformStandardsResponseDto = {
7518
+ type: 'object',
7519
+ properties: {
7520
+ platform: {
7521
+ description: 'The selected platform (institution lock source)',
7522
+ allOf: [
7523
+ {
7524
+ $ref: '#/components/schemas/PlatformStandardsPlatformDto'
7525
+ }
7526
+ ]
7527
+ },
7528
+ region: {
7529
+ type: 'string',
7530
+ description:
7531
+ "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.",
7532
+ example: 'CN'
7533
+ },
7534
+ templates: {
7535
+ description:
7536
+ 'Candidate account-standard templates of the resolved region (groupable by productCategory client-side)',
7537
+ type: 'array',
7538
+ items: {
7539
+ $ref: '#/components/schemas/AccountStandardResponseDto'
7540
+ }
7541
+ }
7542
+ },
7543
+ required: ['platform', 'region', 'templates']
7544
+ } as const;
7545
+
7370
7546
  export const $CreatePlatformDto = {
7371
7547
  type: 'object',
7372
7548
  properties: {
@@ -7468,7 +7644,8 @@ export const $UpdatePlatformDto = {
7468
7644
  },
7469
7645
  isActive: {
7470
7646
  type: 'boolean',
7471
- description: 'Whether the platform is active'
7647
+ description: 'Whether the platform is active',
7648
+ default: true
7472
7649
  }
7473
7650
  }
7474
7651
  } as const;
@@ -7631,7 +7808,8 @@ export const $AccountItemDto = {
7631
7808
  },
7632
7809
  displayName: {
7633
7810
  type: 'string',
7634
- description: 'Display name (last part of account path)',
7811
+ description:
7812
+ 'Display name: user-set name if provided (#762), else the ADR-0114 chain — request-locale catalog name, en pivot, then the last part of the account path (#771)',
7635
7813
  example: 'Savings'
7636
7814
  },
7637
7815
  balance: {
@@ -7667,7 +7845,8 @@ export const $PlatformGroupDto = {
7667
7845
  example: 'CMB Bank'
7668
7846
  },
7669
7847
  accounts: {
7670
- description: 'Accounts within this platform',
7848
+ description:
7849
+ 'Accounts within this platform (Assets and Liabilities rows, #696)',
7671
7850
  type: 'array',
7672
7851
  items: {
7673
7852
  $ref: '#/components/schemas/AccountItemDto'
@@ -7675,7 +7854,8 @@ export const $PlatformGroupDto = {
7675
7854
  },
7676
7855
  totalBalance: {
7677
7856
  type: 'string',
7678
- description: 'FX-converted total balance in base currency',
7857
+ description:
7858
+ 'FX-converted total balance in base currency (nets Assets + Liabilities rows; can be negative)',
7679
7859
  example: '100000.00'
7680
7860
  },
7681
7861
  balanceByCurrency: {
@@ -7694,7 +7874,7 @@ export const $PlatformGroupDto = {
7694
7874
  sharePct: {
7695
7875
  type: 'number',
7696
7876
  description:
7697
- 'Share of the grand converted total (0-100); 0 when grand total is 0',
7877
+ 'Share of the converted asset-side grand total (0-100); liability balances are excluded from the basis; 0 when grand total is 0 (#696)',
7698
7878
  example: 42.5
7699
7879
  }
7700
7880
  },
@@ -7742,7 +7922,8 @@ export const $AccountsSummaryDto = {
7742
7922
  properties: {
7743
7923
  totalAccounts: {
7744
7924
  type: 'number',
7745
- description: 'Total number of accounts'
7925
+ description:
7926
+ 'Total number of accounts (balance sheet: Assets + Liabilities, #696)'
7746
7927
  },
7747
7928
  totalPlatforms: {
7748
7929
  type: 'number',
@@ -7800,7 +7981,8 @@ export const $AccountItemWithAssetClassDto = {
7800
7981
  },
7801
7982
  displayName: {
7802
7983
  type: 'string',
7803
- description: 'Display name (last part of account path)',
7984
+ description:
7985
+ 'Display name: user-set name if provided (#762), else the ADR-0114 chain — request-locale catalog name, en pivot, then the last part of the account path (#771)',
7804
7986
  example: 'Savings'
7805
7987
  },
7806
7988
  balance: {
@@ -8286,7 +8468,7 @@ export const $MonetaryDto = {
8286
8468
  example: 'USD'
8287
8469
  },
8288
8470
  baseCcyEquivalent: {
8289
- type: 'object',
8471
+ type: 'string',
8290
8472
  description: 'Converted to user base currency (Decimal string)',
8291
8473
  example: '21600',
8292
8474
  nullable: true
@@ -8362,13 +8544,13 @@ export const $HoldingPnlRowDto = {
8362
8544
  example: 'Assets:US:Broker:AAPL'
8363
8545
  },
8364
8546
  accountCcy: {
8365
- type: 'object',
8547
+ type: 'string',
8366
8548
  description: 'Account settlement currency (ISO 4217), from cost currency',
8367
8549
  nullable: true,
8368
8550
  example: 'USD'
8369
8551
  },
8370
8552
  brokerType: {
8371
- type: 'object',
8553
+ type: 'string',
8372
8554
  description: 'Broker type derived from Platform.type',
8373
8555
  nullable: true,
8374
8556
  example: 'broker'
@@ -8389,7 +8571,7 @@ export const $HoldingPnlRowDto = {
8389
8571
  example: 'EQUITY'
8390
8572
  },
8391
8573
  assetSubClass: {
8392
- type: 'object',
8574
+ type: 'string',
8393
8575
  nullable: true,
8394
8576
  example: 'STOCK'
8395
8577
  },
@@ -8436,14 +8618,14 @@ export const $HoldingPnlRowDto = {
8436
8618
  ]
8437
8619
  },
8438
8620
  unrealizedPnlBase: {
8439
- type: 'object',
8621
+ type: 'string',
8440
8622
  description:
8441
8623
  'Unrealized P&L in base currency (Decimal string); null when any FX/price missing',
8442
8624
  nullable: true,
8443
8625
  example: '6000'
8444
8626
  },
8445
8627
  unrealizedPnlPct: {
8446
- type: 'object',
8628
+ type: 'string',
8447
8629
  description: 'Unrealized P&L % (Decimal string)',
8448
8630
  nullable: true,
8449
8631
  example: '25'
@@ -8467,7 +8649,7 @@ export const $HoldingPnlRowDto = {
8467
8649
  ]
8468
8650
  },
8469
8651
  pctOfInvestedAssets: {
8470
- type: 'object',
8652
+ type: 'string',
8471
8653
  description:
8472
8654
  'Share of invested assets % (Decimal string); only for invested chartTokens',
8473
8655
  nullable: true,
@@ -8512,15 +8694,15 @@ export const $HoldingPnlWarningDto = {
8512
8694
  ]
8513
8695
  },
8514
8696
  symbol: {
8515
- type: 'object',
8697
+ type: 'string',
8516
8698
  nullable: true
8517
8699
  },
8518
8700
  accountId: {
8519
- type: 'object',
8701
+ type: 'string',
8520
8702
  nullable: true
8521
8703
  },
8522
8704
  currency: {
8523
- type: 'object',
8705
+ type: 'string',
8524
8706
  nullable: true
8525
8707
  }
8526
8708
  },
@@ -8802,35 +8984,35 @@ export const $SymbolSearchResultDto = {
8802
8984
  example: 'AAPL'
8803
8985
  },
8804
8986
  name: {
8805
- type: 'object',
8987
+ type: 'string',
8806
8988
  example: 'Apple Inc.',
8807
8989
  nullable: true
8808
8990
  },
8809
8991
  exchange: {
8810
- type: 'object',
8992
+ type: 'string',
8811
8993
  example: 'US',
8812
8994
  nullable: true
8813
8995
  },
8814
8996
  assetType: {
8815
- type: 'object',
8997
+ type: 'string',
8816
8998
  description: 'OpenBB asset_type (e.g. stock, etf)',
8817
8999
  example: 'stock',
8818
9000
  nullable: true
8819
9001
  },
8820
9002
  assetClass: {
8821
- type: 'object',
9003
+ type: 'string',
8822
9004
  description: 'IGN asset class (region.types.ts ASSET_CLASSES)',
8823
9005
  example: 'EQUITY',
8824
9006
  nullable: true
8825
9007
  },
8826
9008
  assetSubClass: {
8827
- type: 'object',
9009
+ type: 'string',
8828
9010
  description: 'IGN asset sub-class (region.types.ts ASSET_SUB_CLASSES)',
8829
9011
  example: 'STOCK',
8830
9012
  nullable: true
8831
9013
  },
8832
9014
  currency: {
8833
- type: 'object',
9015
+ type: 'string',
8834
9016
  description: 'Trading currency (extra_data or inferred from exchange)',
8835
9017
  example: 'USD',
8836
9018
  nullable: true
@@ -8847,90 +9029,90 @@ export const $SymbolQuoteDto = {
8847
9029
  example: 'AAPL'
8848
9030
  },
8849
9031
  name: {
8850
- type: 'object',
9032
+ type: 'string',
8851
9033
  example: 'Apple Inc.',
8852
9034
  nullable: true
8853
9035
  },
8854
9036
  exchange: {
8855
- type: 'object',
9037
+ type: 'string',
8856
9038
  example: 'US',
8857
9039
  nullable: true
8858
9040
  },
8859
9041
  assetType: {
8860
- type: 'object',
9042
+ type: 'string',
8861
9043
  description: 'OpenBB asset_type',
8862
9044
  example: 'stock',
8863
9045
  nullable: true
8864
9046
  },
8865
9047
  assetClass: {
8866
- type: 'object',
9048
+ type: 'string',
8867
9049
  description: 'IGN asset class',
8868
9050
  example: 'EQUITY',
8869
9051
  nullable: true
8870
9052
  },
8871
9053
  assetSubClass: {
8872
- type: 'object',
9054
+ type: 'string',
8873
9055
  description: 'IGN asset sub-class',
8874
9056
  example: 'STOCK',
8875
9057
  nullable: true
8876
9058
  },
8877
9059
  currency: {
8878
- type: 'object',
9060
+ type: 'string',
8879
9061
  description: 'Trading currency (extra_data or inferred from exchange)',
8880
9062
  example: 'USD',
8881
9063
  nullable: true
8882
9064
  },
8883
9065
  price: {
8884
- type: 'object',
9066
+ type: 'string',
8885
9067
  description: 'Latest price (Decimal string)',
8886
9068
  example: '189.84',
8887
9069
  nullable: true
8888
9070
  },
8889
9071
  priceDate: {
8890
- type: 'object',
9072
+ type: 'string',
8891
9073
  description: 'Date the price was observed (ISO yyyy-MM-dd)',
8892
9074
  example: '2026-08-05',
8893
9075
  nullable: true
8894
9076
  },
8895
9077
  changePercent: {
8896
- type: 'object',
9078
+ type: 'number',
8897
9079
  description:
8898
9080
  'Change vs previous close, in percentage points (1.7 == 1.7%). openbb stores change_percent as a normalized decimal; this exposes percentage points for frontend convenience.',
8899
9081
  example: 1.7,
8900
9082
  nullable: true
8901
9083
  },
8902
9084
  prevClose: {
8903
- type: 'object',
9085
+ type: 'string',
8904
9086
  description: 'Previous close (Decimal string)',
8905
9087
  nullable: true
8906
9088
  },
8907
9089
  open: {
8908
- type: 'object',
9090
+ type: 'string',
8909
9091
  description: 'Day open (Decimal string)',
8910
9092
  nullable: true
8911
9093
  },
8912
9094
  high: {
8913
- type: 'object',
9095
+ type: 'string',
8914
9096
  description: 'Day high (Decimal string)',
8915
9097
  nullable: true
8916
9098
  },
8917
9099
  low: {
8918
- type: 'object',
9100
+ type: 'string',
8919
9101
  description: 'Day low (Decimal string)',
8920
9102
  nullable: true
8921
9103
  },
8922
9104
  volume: {
8923
- type: 'object',
9105
+ type: 'string',
8924
9106
  description: 'Day volume (Decimal string)',
8925
9107
  nullable: true
8926
9108
  },
8927
9109
  yearHigh: {
8928
- type: 'object',
9110
+ type: 'string',
8929
9111
  description: '52-week high (Decimal string)',
8930
9112
  nullable: true
8931
9113
  },
8932
9114
  yearLow: {
8933
- type: 'object',
9115
+ type: 'string',
8934
9116
  description: '52-week low (Decimal string)',
8935
9117
  nullable: true
8936
9118
  }