@firela/api-types 0.0.0-canary.8bf286b3 → 0.0.0-canary.8c76fd39

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.
@@ -197,7 +197,7 @@ export const $AccountResponseDto = {
197
197
  }
198
198
  },
199
199
  platformId: {
200
- type: 'object',
200
+ type: 'string',
201
201
  description: 'Platform ID (null if unbound)',
202
202
  example: 'c98e5d4a-2f71-4a5a-bb3c-92c9f231d5e2'
203
203
  },
@@ -377,16 +377,43 @@ export const $AccountStandardResponseDto = {
377
377
  },
378
378
  name: {
379
379
  type: 'string',
380
- description: 'Short localized display name',
380
+ description:
381
+ '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
382
  example: 'Housing Fund'
382
383
  },
384
+ aliases: {
385
+ description:
386
+ '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.',
387
+ example: ['Alipay', 'WeChat Pay'],
388
+ type: 'array',
389
+ items: {
390
+ type: 'string'
391
+ }
392
+ },
393
+ searchTerms: {
394
+ description:
395
+ '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).',
396
+ example: ['yinhangka', 'jiejika'],
397
+ type: 'array',
398
+ items: {
399
+ type: 'string'
400
+ }
401
+ },
402
+ currency: {
403
+ type: 'string',
404
+ description:
405
+ '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).',
406
+ example: 'HKD'
407
+ },
383
408
  description: {
384
409
  type: 'string',
385
- description: 'Account description (stable semantics only)',
410
+ description:
411
+ '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
412
  example: 'ICBC checking account for daily transactions'
387
413
  },
388
414
  tags: {
389
- description: 'Account tags for categorization',
415
+ description:
416
+ 'Account tags for categorization — structured metadata delivered verbatim (not localized, not xlf-managed). ADR-0131 class A.',
390
417
  example: ['bank', 'checking', 'primary'],
391
418
  type: 'array',
392
419
  items: {
@@ -498,7 +525,10 @@ export const $RegionConfigDto = {
498
525
  },
499
526
  locale: {
500
527
  type: 'string',
501
- example: 'de-DE'
528
+ example: 'de-DE',
529
+ pattern: '^[a-z]{2,8}-[A-Z]{2}$',
530
+ description:
531
+ "Region-qualified BCP-47 tag whose region subtag equals the region's own ISO 3166-1 code (e.g., ja-JP, zh-CN, en-HK)"
502
532
  }
503
533
  },
504
534
  required: ['currency', 'dateFormat', 'locale']
@@ -1445,13 +1475,13 @@ export const $TransactionListItemDto = {
1445
1475
  viewpointAmount: {
1446
1476
  type: 'string',
1447
1477
  description:
1448
- 'Per-leg sign-normalized row amount for the category viewpoint (ADR-0126): each posting on the category account set contributes its unitsNumber with Income-root legs negated and Expenses-root legs identity. Positive under normal booking but NOT clamped (explicit negative expense legs and net-flip refund months stay negative). Omitted outside the category viewpoint.',
1478
+ '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
1479
  example: '10000.00'
1450
1480
  },
1451
1481
  viewpointCurrency: {
1452
1482
  type: 'string',
1453
1483
  description:
1454
- 'Currency of viewpointAmount. A row spanning multiple currencies takes the largest-magnitude currency group (known simplification, ADR-0126). Omitted outside the category viewpoint.',
1484
+ 'Currency of viewpointAmount. A row spanning multiple currencies takes the largest-magnitude currency group (known simplification, ADR-0126).',
1455
1485
  example: 'CNY'
1456
1486
  }
1457
1487
  },
@@ -2510,10 +2540,10 @@ export const $UpdatePayeeDto = {
2510
2540
  meta: {
2511
2541
  type: 'object',
2512
2542
  description:
2513
- 'Metadata for extended information (location, notes, contact info, etc.). Will merge with existing metadata.',
2543
+ 'Metadata for extended information (location, notes, contact info, etc.)',
2514
2544
  example: {
2515
2545
  location: 'Zhongguancun',
2516
- note: 'Updated note',
2546
+ note: 'Near subway station',
2517
2547
  favorite: true
2518
2548
  }
2519
2549
  },
@@ -3074,568 +3104,660 @@ export const $UpdateCommodityDto = {
3074
3104
  }
3075
3105
  } as const;
3076
3106
 
3077
- export const $CreateBeanPriceDto = {
3107
+ export const $CurrencyBalanceDto = {
3078
3108
  type: 'object',
3079
3109
  properties: {
3080
3110
  currency: {
3081
3111
  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)',
3112
+ description: 'ISO 4217 currency code',
3088
3113
  example: 'CNY'
3089
3114
  },
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: {
3115
+ balance: {
3098
3116
  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
- }
3117
+ description: 'Balance amount',
3118
+ example: '500000.00'
3111
3119
  }
3112
3120
  },
3113
- required: ['currency', 'quoteCurrency', 'amount', 'date']
3121
+ required: ['currency', 'balance']
3114
3122
  } as const;
3115
3123
 
3116
- export const $PriceResponseDto = {
3124
+ export const $TimeSeriesPointDto = {
3117
3125
  type: 'object',
3118
3126
  properties: {
3119
- id: {
3127
+ date: {
3120
3128
  type: 'string',
3121
- description: 'Unique identifier',
3122
- example: 'uuid-123-456'
3129
+ description: 'Date in YYYY-MM-DD format',
3130
+ example: '2024-06-15'
3123
3131
  },
3124
- userId: {
3132
+ value: {
3125
3133
  type: 'string',
3126
- description: 'User ID (owner of the price)',
3127
- example: 'user-123'
3134
+ description: 'Value at this date (in base currency)',
3135
+ example: '500000.00'
3128
3136
  },
3129
- currency: {
3137
+ change: {
3130
3138
  type: 'string',
3131
- description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3132
- example: 'BTC'
3139
+ description: 'Change from previous point',
3140
+ example: '5000.00'
3133
3141
  },
3134
- quoteCurrency: {
3142
+ assets: {
3135
3143
  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
3144
+ description: 'Total assets at this date (in base currency)',
3145
+ example: '494338.00'
3144
3146
  },
3145
- date: {
3147
+ liabilities: {
3146
3148
  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'
3149
+ description: 'Total liabilities at this date (in base currency)',
3150
+ example: '310098.00'
3151
3151
  },
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
3152
+ byCurrency: {
3153
+ description: 'Multi-currency breakdown for this point',
3154
+ type: 'array',
3155
+ items: {
3156
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3160
3157
  }
3158
+ }
3159
+ },
3160
+ required: ['date', 'value']
3161
+ } as const;
3162
+
3163
+ export const $TrendSummaryDto = {
3164
+ type: 'object',
3165
+ properties: {
3166
+ startValue: {
3167
+ type: 'string',
3168
+ description: 'Value at start of period',
3169
+ example: '450000.00'
3161
3170
  },
3162
- createdAt: {
3163
- format: 'date-time',
3171
+ endValue: {
3164
3172
  type: 'string',
3165
- description: 'Creation timestamp',
3166
- example: '2024-11-03T10:00:00Z'
3173
+ description: 'Value at end of period',
3174
+ example: '500000.00'
3167
3175
  },
3168
- updatedAt: {
3169
- format: 'date-time',
3176
+ totalChange: {
3170
3177
  type: 'string',
3171
- description: 'Last update timestamp',
3172
- example: '2024-11-03T10:00:00Z'
3178
+ description: 'Total change over period',
3179
+ example: '50000.00'
3180
+ },
3181
+ totalChangePercentage: {
3182
+ type: 'string',
3183
+ description: 'Total change percentage',
3184
+ example: '+11.11%'
3173
3185
  }
3174
3186
  },
3175
- required: [
3176
- 'id',
3177
- 'userId',
3178
- 'currency',
3179
- 'quoteCurrency',
3180
- 'amount',
3181
- 'date',
3182
- 'meta',
3183
- 'createdAt',
3184
- 'updatedAt'
3185
- ]
3187
+ required: ['startValue', 'endValue', 'totalChange', 'totalChangePercentage']
3186
3188
  } as const;
3187
3189
 
3188
- export const $PriceListResponseDto = {
3190
+ export const $MultiCurrencyPointDto = {
3189
3191
  type: 'object',
3190
3192
  properties: {
3191
- items: {
3192
- description: 'List of prices',
3193
+ date: {
3194
+ type: 'string',
3195
+ description: 'Date in YYYY-MM-DD format',
3196
+ example: '2024-06-15'
3197
+ },
3198
+ byCurrency: {
3199
+ description: 'Balances by currency',
3193
3200
  type: 'array',
3194
3201
  items: {
3195
- $ref: '#/components/schemas/PriceResponseDto'
3202
+ $ref: '#/components/schemas/CurrencyBalanceDto'
3196
3203
  }
3197
- },
3198
- total: {
3199
- type: 'number',
3200
- description: 'Total number of prices',
3201
- example: 42
3202
3204
  }
3203
3205
  },
3204
- required: ['items', 'total']
3206
+ required: ['date', 'byCurrency']
3205
3207
  } as const;
3206
3208
 
3207
- export const $UpdateBeanPriceDto = {
3209
+ export const $PortfolioTrendsResponseDto = {
3208
3210
  type: 'object',
3209
3211
  properties: {
3210
- currency: {
3211
- type: 'string',
3212
- description: 'Currency being priced'
3212
+ series: {
3213
+ description: 'Time series data points',
3214
+ type: 'array',
3215
+ items: {
3216
+ $ref: '#/components/schemas/TimeSeriesPointDto'
3217
+ }
3213
3218
  },
3214
- quoteCurrency: {
3219
+ summary: {
3220
+ description: 'Period summary',
3221
+ allOf: [
3222
+ {
3223
+ $ref: '#/components/schemas/TrendSummaryDto'
3224
+ }
3225
+ ]
3226
+ },
3227
+ period: {
3215
3228
  type: 'string',
3216
- description: 'Quote currency (pricing currency)'
3229
+ description: 'Period requested',
3230
+ example: '6m'
3217
3231
  },
3218
- amount: {
3219
- type: 'number',
3220
- description: 'Price amount (MUST be >= 0 per Beancount spec)',
3221
- minimum: 0
3232
+ granularity: {
3233
+ type: 'string',
3234
+ description: 'Data granularity',
3235
+ example: 'month'
3222
3236
  },
3223
- date: {
3237
+ currency: {
3224
3238
  type: 'string',
3225
- description: 'Price date (ISO 8601 format)'
3239
+ description: 'Base currency for converted values',
3240
+ example: 'CNY'
3226
3241
  },
3227
- metadata: {
3228
- type: 'object',
3229
- description: 'Metadata'
3242
+ byCurrency: {
3243
+ description:
3244
+ 'Multi-currency time series (each point has currency breakdown)',
3245
+ type: 'array',
3246
+ items: {
3247
+ $ref: '#/components/schemas/MultiCurrencyPointDto'
3248
+ }
3249
+ },
3250
+ warnings: {
3251
+ description: 'Exchange rate warnings',
3252
+ type: 'array',
3253
+ items: {
3254
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3255
+ }
3230
3256
  }
3231
- }
3257
+ },
3258
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3232
3259
  } as const;
3233
3260
 
3234
- export const $CreateRecurringRuleDto = {
3261
+ export const $CashFlowPointDto = {
3235
3262
  type: 'object',
3236
3263
  properties: {
3237
- name: {
3264
+ month: {
3238
3265
  type: 'string',
3239
- description: 'Rule name (unique per user)',
3240
- maxLength: 100
3266
+ description: 'Month key (YYYY-MM)',
3267
+ example: '2024-03'
3241
3268
  },
3242
- icon: {
3269
+ income: {
3243
3270
  type: 'string',
3244
- description: 'Icon emoji',
3245
- maxLength: 10
3271
+ description: 'Income in base currency (absolute, converted)',
3272
+ example: '10000.00'
3246
3273
  },
3247
- frequency: {
3274
+ expense: {
3248
3275
  type: 'string',
3249
- description: 'Recurring frequency',
3250
- enum: [
3251
- 'WEEKLY',
3252
- 'BIWEEKLY',
3253
- 'MONTHLY',
3254
- 'BIMONTHLY',
3255
- 'QUARTERLY',
3256
- 'YEARLY',
3257
- 'CUSTOM'
3258
- ]
3259
- },
3260
- expectedAmount: {
3261
- type: 'number',
3262
- description: 'Expected amount (positive number)',
3263
- minimum: 0
3264
- },
3265
- expectedDay: {
3266
- type: 'number',
3267
- description: 'Expected day of month (1-31)',
3268
- minimum: 1,
3269
- maximum: 31
3270
- },
3271
- customIntervalDays: {
3272
- type: 'number',
3273
- description: 'Custom interval in days (required for CUSTOM frequency)',
3274
- minimum: 1
3275
- },
3276
- currency: {
3277
- type: 'string',
3278
- description: 'Currency code',
3279
- default: 'CNY',
3280
- maxLength: 10
3281
- },
3282
- matchPayeePattern: {
3283
- type: 'string',
3284
- description: 'Payee matching pattern (supports wildcards)',
3285
- maxLength: 200
3286
- },
3287
- matchAmountTolerance: {
3288
- type: 'number',
3289
- description: 'Amount tolerance percentage (0-1)',
3290
- default: 0.075,
3291
- minimum: 0,
3292
- maximum: 1
3276
+ description: 'Expense in base currency (absolute, converted)',
3277
+ example: '5000.00'
3293
3278
  },
3294
- defaultExpenseAccount: {
3279
+ netSavings: {
3295
3280
  type: 'string',
3296
- description: 'Default expense account for auto-create',
3297
- maxLength: 200
3298
- },
3299
- defaultPaymentAccount: {
3281
+ description: 'netSavings = income − expense (savings positive)',
3282
+ example: '5000.00'
3283
+ }
3284
+ },
3285
+ required: ['month', 'income', 'expense', 'netSavings']
3286
+ } as const;
3287
+
3288
+ export const $CashFlowTrendSummaryDto = {
3289
+ type: 'object',
3290
+ properties: {
3291
+ totalIncome: {
3300
3292
  type: 'string',
3301
- description: 'Default payment account for auto-create',
3302
- maxLength: 200
3293
+ description: 'Total income across the period',
3294
+ example: '60000.00'
3303
3295
  },
3304
- defaultPayee: {
3296
+ totalExpense: {
3305
3297
  type: 'string',
3306
- description: 'Default payee for auto-create',
3307
- maxLength: 200
3308
- },
3309
- autoCreate: {
3310
- type: 'boolean',
3311
- description: 'Auto-create transaction when expected date arrives',
3312
- default: false
3298
+ description: 'Total expense across the period',
3299
+ example: '30000.00'
3313
3300
  },
3314
- startDate: {
3301
+ totalNetSavings: {
3315
3302
  type: 'string',
3316
- description: 'Rule start date (ISO format)'
3303
+ description: 'income expense across the period',
3304
+ example: '30000.00'
3317
3305
  },
3318
- endDate: {
3306
+ averageMonthlyNetSavings: {
3319
3307
  type: 'string',
3320
- description: 'Rule end date (ISO format)'
3308
+ description:
3309
+ 'totalNetSavings divided by the window length (N months, incl. zero-filled)',
3310
+ example: '5000.00'
3321
3311
  }
3322
3312
  },
3323
3313
  required: [
3324
- 'name',
3325
- 'frequency',
3326
- 'expectedAmount',
3327
- 'currency',
3328
- 'matchAmountTolerance',
3329
- 'autoCreate'
3314
+ 'totalIncome',
3315
+ 'totalExpense',
3316
+ 'totalNetSavings',
3317
+ 'averageMonthlyNetSavings'
3330
3318
  ]
3331
3319
  } as const;
3332
3320
 
3333
- export const $RecurringRuleResponseDto = {
3321
+ export const $CashFlowTrendsResponseDto = {
3334
3322
  type: 'object',
3335
3323
  properties: {
3336
- id: {
3324
+ series: {
3325
+ description:
3326
+ 'Monthly cash-flow series (fixed N-month window, zero-filled)',
3327
+ type: 'array',
3328
+ items: {
3329
+ $ref: '#/components/schemas/CashFlowPointDto'
3330
+ }
3331
+ },
3332
+ summary: {
3333
+ description: 'Period totals',
3334
+ allOf: [
3335
+ {
3336
+ $ref: '#/components/schemas/CashFlowTrendSummaryDto'
3337
+ }
3338
+ ]
3339
+ },
3340
+ period: {
3337
3341
  type: 'string',
3338
- description: 'Rule ID'
3342
+ description: 'Period requested',
3343
+ example: '6m'
3339
3344
  },
3340
- userId: {
3345
+ granularity: {
3341
3346
  type: 'string',
3342
- description: 'User ID'
3347
+ description: 'Data granularity (v1 returns month buckets)',
3348
+ example: 'month'
3343
3349
  },
3344
- name: {
3350
+ currency: {
3345
3351
  type: 'string',
3346
- description: 'Rule name'
3352
+ description: 'Base currency for converted values',
3353
+ example: 'CNY'
3347
3354
  },
3348
- icon: {
3349
- type: 'object',
3350
- description: 'Icon emoji'
3355
+ warnings: {
3356
+ description: 'Exchange rate warnings (e.g. missing rate for a currency)',
3357
+ type: 'array',
3358
+ items: {
3359
+ $ref: '#/components/schemas/ExchangeRateWarningDto'
3360
+ }
3361
+ }
3362
+ },
3363
+ required: ['series', 'summary', 'period', 'granularity', 'currency']
3364
+ } as const;
3365
+
3366
+ export const $GenerateSnapshotBody = {
3367
+ type: 'object',
3368
+ properties: {}
3369
+ } as const;
3370
+
3371
+ export const $GenerateSnapshotResponse = {
3372
+ type: 'object',
3373
+ properties: {}
3374
+ } as const;
3375
+
3376
+ export const $BackfillSnapshotsBody = {
3377
+ type: 'object',
3378
+ properties: {}
3379
+ } as const;
3380
+
3381
+ export const $BackfillSnapshotsResponse = {
3382
+ type: 'object',
3383
+ properties: {}
3384
+ } as const;
3385
+
3386
+ export const $CreateBeanPriceDto = {
3387
+ type: 'object',
3388
+ properties: {
3389
+ currency: {
3390
+ type: 'string',
3391
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3392
+ example: 'USD'
3351
3393
  },
3352
- frequency: {
3394
+ quoteCurrency: {
3353
3395
  type: 'string',
3354
- description: 'Recurring frequency'
3396
+ description: 'Quote currency (pricing currency, e.g., CNY, EUR)',
3397
+ example: 'CNY'
3355
3398
  },
3356
- expectedAmount: {
3399
+ amount: {
3357
3400
  type: 'number',
3358
- description: 'Expected amount'
3401
+ description:
3402
+ 'Price amount (MUST be >= 0 per Beancount spec, supports up to 15 decimal places). Zero allowed for conversion entries, negative strictly prohibited.',
3403
+ example: 175.5,
3404
+ minimum: 0
3359
3405
  },
3360
- expectedDay: {
3361
- type: 'object',
3362
- description: 'Expected day of month'
3406
+ date: {
3407
+ type: 'string',
3408
+ description: 'Price date (ISO 8601 format)',
3409
+ example: '2024-11-05'
3363
3410
  },
3364
- customIntervalDays: {
3411
+ metadata: {
3365
3412
  type: 'object',
3366
- description: 'Custom interval in days'
3413
+ description:
3414
+ 'Metadata (validated by Zod schema, max field lengths enforced)',
3415
+ example: {
3416
+ source: 'MANUAL',
3417
+ note: 'Bank valuation report',
3418
+ confidence: 0.95
3419
+ }
3420
+ }
3421
+ },
3422
+ required: ['currency', 'quoteCurrency', 'amount', 'date']
3423
+ } as const;
3424
+
3425
+ export const $PriceResponseDto = {
3426
+ type: 'object',
3427
+ properties: {
3428
+ id: {
3429
+ type: 'string',
3430
+ description: 'Unique identifier',
3431
+ example: 'uuid-123-456'
3432
+ },
3433
+ userId: {
3434
+ type: 'string',
3435
+ description: 'User ID (owner of the price)',
3436
+ example: 'user-123'
3367
3437
  },
3368
3438
  currency: {
3369
3439
  type: 'string',
3370
- description: 'Currency code'
3440
+ description: 'Currency being priced (e.g., USD, AAPL, BTC)',
3441
+ example: 'BTC'
3371
3442
  },
3372
- matchPayeePattern: {
3373
- type: 'object',
3374
- description: 'Payee matching pattern'
3443
+ quoteCurrency: {
3444
+ type: 'string',
3445
+ description: 'Quote currency (pricing currency, e.g., USD, CNY)',
3446
+ example: 'USD'
3375
3447
  },
3376
- matchAmountTolerance: {
3448
+ amount: {
3377
3449
  type: 'number',
3378
- description: 'Amount tolerance percentage'
3379
- },
3380
- defaultExpenseAccount: {
3381
- type: 'object',
3382
- description: 'Default expense account'
3450
+ description:
3451
+ 'Price amount (corresponds to Beancount Amount.number). Supports up to 15 decimal places.',
3452
+ example: 50000
3383
3453
  },
3384
- defaultPaymentAccount: {
3385
- type: 'object',
3386
- description: 'Default payment account'
3454
+ date: {
3455
+ type: 'string',
3456
+ description:
3457
+ 'Price date (ISO 8601 format). Represents the date this price was valid.',
3458
+ example: '2024-01-01',
3459
+ format: 'date'
3387
3460
  },
3388
- defaultPayee: {
3461
+ meta: {
3389
3462
  type: 'object',
3390
- description: 'Default payee'
3391
- },
3392
- isActive: {
3393
- type: 'boolean',
3394
- description: 'Whether rule is active'
3463
+ description:
3464
+ 'Metadata (corresponds to Beancount meta field). Contains source, confidence, note, etc.',
3465
+ example: {
3466
+ source: 'MANUAL',
3467
+ note: 'User-defined price',
3468
+ confidence: 1
3469
+ }
3395
3470
  },
3396
- startDate: {
3471
+ createdAt: {
3472
+ format: 'date-time',
3397
3473
  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'
3474
+ description: 'Creation timestamp',
3475
+ example: '2024-11-03T10:00:00Z'
3420
3476
  },
3421
3477
  updatedAt: {
3422
3478
  format: 'date-time',
3423
3479
  type: 'string',
3424
- description: 'Updated at timestamp'
3480
+ description: 'Last update timestamp',
3481
+ example: '2024-11-03T10:00:00Z'
3425
3482
  }
3426
3483
  },
3427
3484
  required: [
3428
3485
  'id',
3429
3486
  'userId',
3430
- 'name',
3431
- 'frequency',
3432
- 'expectedAmount',
3433
3487
  'currency',
3434
- 'matchAmountTolerance',
3435
- 'isActive',
3436
- 'startDate',
3437
- 'autoCreate',
3438
- 'totalCount',
3488
+ 'quoteCurrency',
3489
+ 'amount',
3490
+ 'date',
3491
+ 'meta',
3439
3492
  'createdAt',
3440
3493
  'updatedAt'
3441
3494
  ]
3442
3495
  } as const;
3443
3496
 
3444
- export const $CreateRuleFromTransactionDto = {
3497
+ export const $PriceListResponseDto = {
3445
3498
  type: 'object',
3446
3499
  properties: {
3447
- frequency: {
3500
+ items: {
3501
+ description: 'List of prices',
3502
+ type: 'array',
3503
+ items: {
3504
+ $ref: '#/components/schemas/PriceResponseDto'
3505
+ }
3506
+ },
3507
+ total: {
3508
+ type: 'number',
3509
+ description: 'Total number of prices',
3510
+ example: 42
3511
+ }
3512
+ },
3513
+ required: ['items', 'total']
3514
+ } as const;
3515
+
3516
+ export const $UpdateBeanPriceDto = {
3517
+ type: 'object',
3518
+ properties: {
3519
+ currency: {
3448
3520
  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'
3521
+ description: 'Currency being priced'
3460
3522
  },
3461
- name: {
3523
+ quoteCurrency: {
3462
3524
  type: 'string',
3463
- description: 'Optional name override (default: transaction payee)',
3464
- maxLength: 100
3525
+ description: 'Quote currency (pricing currency)'
3465
3526
  },
3466
- icon: {
3527
+ amount: {
3528
+ type: 'number',
3529
+ description: 'Price amount (MUST be >= 0 per Beancount spec)',
3530
+ minimum: 0
3531
+ },
3532
+ date: {
3467
3533
  type: 'string',
3468
- description: 'Optional icon emoji',
3469
- maxLength: 10
3534
+ description: 'Price date (ISO 8601 format)'
3535
+ },
3536
+ metadata: {
3537
+ type: 'object',
3538
+ description: 'Metadata'
3539
+ }
3540
+ }
3541
+ } as const;
3542
+
3543
+ export const $DeleteOwnUserDto = {
3544
+ type: 'object',
3545
+ properties: {
3546
+ accessToken: {
3547
+ type: 'string',
3548
+ description: 'Access token for user verification',
3549
+ example: 'abc123xyz'
3470
3550
  }
3471
3551
  },
3472
- required: ['frequency']
3552
+ required: ['accessToken']
3473
3553
  } as const;
3474
3554
 
3475
- export const $RecurringRuleWithStatsResponseDto = {
3555
+ export const $UserSettingsResponseDto = {
3556
+ type: 'object',
3557
+ properties: {
3558
+ baseCurrency: {
3559
+ type: 'string',
3560
+ description:
3561
+ '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).',
3562
+ example: 'USD',
3563
+ nullable: true
3564
+ }
3565
+ },
3566
+ required: ['baseCurrency']
3567
+ } as const;
3568
+
3569
+ export const $UserResponseDto = {
3476
3570
  type: 'object',
3477
3571
  properties: {
3478
3572
  id: {
3479
3573
  type: 'string',
3480
- description: 'Rule ID'
3574
+ description: 'User ID'
3481
3575
  },
3482
- userId: {
3576
+ role: {
3483
3577
  type: 'string',
3484
- description: 'User ID'
3578
+ description: 'Assigned user role'
3485
3579
  },
3486
- name: {
3580
+ permissions: {
3581
+ description: 'Permission strings',
3582
+ type: 'array',
3583
+ items: {
3584
+ type: 'string'
3585
+ }
3586
+ },
3587
+ settings: {
3588
+ description: 'User settings',
3589
+ allOf: [
3590
+ {
3591
+ $ref: '#/components/schemas/UserSettingsResponseDto'
3592
+ }
3593
+ ]
3594
+ }
3595
+ },
3596
+ required: ['id', 'role', 'permissions', 'settings']
3597
+ } as const;
3598
+
3599
+ export const $SignupDto = {
3600
+ type: 'object',
3601
+ properties: {
3602
+ turnstileToken: {
3487
3603
  type: 'string',
3488
- description: 'Rule name'
3604
+ description:
3605
+ 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
3606
+ example: '0.abc123def456...'
3607
+ }
3608
+ }
3609
+ } as const;
3610
+
3611
+ export const $SignupResponseDto = {
3612
+ type: 'object',
3613
+ properties: {
3614
+ authToken: {
3615
+ type: 'string',
3616
+ description: 'JWT auth token',
3617
+ example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
3489
3618
  },
3490
- icon: {
3491
- type: 'object',
3492
- description: 'Icon emoji'
3619
+ accessToken: {
3620
+ type: 'string',
3621
+ description: 'Auto-generated access token'
3493
3622
  },
3494
- frequency: {
3623
+ role: {
3495
3624
  type: 'string',
3496
- description: 'Recurring frequency'
3625
+ description: 'Assigned user role',
3626
+ enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
3627
+ }
3628
+ },
3629
+ required: ['authToken', 'accessToken', 'role']
3630
+ } as const;
3631
+
3632
+ export const $UpdateUserSettingDto = {
3633
+ type: 'object',
3634
+ properties: {
3635
+ secId: {
3636
+ type: 'number',
3637
+ description: 'Security ID'
3497
3638
  },
3498
- expectedAmount: {
3639
+ annualInterestRate: {
3499
3640
  type: 'number',
3500
- description: 'Expected amount'
3641
+ description: 'Annual interest rate',
3642
+ example: 0.05
3501
3643
  },
3502
- expectedDay: {
3503
- type: 'object',
3504
- description: 'Expected day of month'
3644
+ currency: {
3645
+ type: 'string',
3646
+ description: 'Currency code',
3647
+ example: 'USD'
3505
3648
  },
3506
- customIntervalDays: {
3507
- type: 'object',
3508
- description: 'Custom interval in days'
3649
+ baseCurrency: {
3650
+ type: 'string',
3651
+ description: 'Base currency code',
3652
+ example: 'USD'
3509
3653
  },
3510
- currency: {
3654
+ benchmark: {
3511
3655
  type: 'string',
3512
- description: 'Currency code'
3656
+ description: 'Benchmark symbol',
3657
+ example: 'SPY'
3513
3658
  },
3514
- matchPayeePattern: {
3515
- type: 'object',
3516
- description: 'Payee matching pattern'
3659
+ colorScheme: {
3660
+ type: 'string',
3661
+ description: 'Color scheme',
3662
+ enum: ['DARK', 'LIGHT']
3517
3663
  },
3518
- matchAmountTolerance: {
3664
+ dateRange: {
3665
+ type: 'string',
3666
+ description: 'Date range filter',
3667
+ example: '1y'
3668
+ },
3669
+ emergencyFund: {
3519
3670
  type: 'number',
3520
- description: 'Amount tolerance percentage'
3671
+ description: 'Emergency fund amount',
3672
+ example: 10000
3521
3673
  },
3522
- defaultExpenseAccount: {
3523
- type: 'object',
3524
- description: 'Default expense account'
3674
+ 'filters.accounts': {
3675
+ description: 'Account filter IDs',
3676
+ type: 'array',
3677
+ items: {
3678
+ type: 'string'
3679
+ }
3525
3680
  },
3526
- defaultPaymentAccount: {
3527
- type: 'object',
3528
- description: 'Default payment account'
3681
+ 'filters.assetClasses': {
3682
+ description: 'Asset class filters',
3683
+ type: 'array',
3684
+ items: {
3685
+ type: 'string'
3686
+ }
3529
3687
  },
3530
- defaultPayee: {
3531
- type: 'object',
3532
- description: 'Default payee'
3688
+ 'filters.dataSource': {
3689
+ type: 'string',
3690
+ description: 'Data source filter'
3533
3691
  },
3534
- isActive: {
3535
- type: 'boolean',
3536
- description: 'Whether rule is active'
3537
- },
3538
- startDate: {
3692
+ 'filters.symbol': {
3539
3693
  type: 'string',
3540
- description: 'Rule start date (YYYY-MM-DD)'
3694
+ description: 'Symbol filter'
3541
3695
  },
3542
- endDate: {
3543
- type: 'object',
3544
- description: 'Rule end date (YYYY-MM-DD)'
3696
+ 'filters.tags': {
3697
+ description: 'Tag filters',
3698
+ type: 'array',
3699
+ items: {
3700
+ type: 'string'
3701
+ }
3545
3702
  },
3546
- autoCreate: {
3703
+ isExperimentalFeatures: {
3547
3704
  type: 'boolean',
3548
- description: 'Auto-create transaction on expected date'
3549
- },
3550
- lastOccurrence: {
3551
- type: 'object',
3552
- description: 'Last matched occurrence date (YYYY-MM-DD)'
3705
+ description: 'Enable experimental features'
3553
3706
  },
3554
- totalCount: {
3555
- type: 'number',
3556
- description: 'Total matched transactions count'
3707
+ isRestrictedView: {
3708
+ type: 'boolean',
3709
+ description: 'Enable restricted view mode'
3557
3710
  },
3558
- createdAt: {
3559
- format: 'date-time',
3711
+ language: {
3560
3712
  type: 'string',
3561
- description: 'Created at timestamp'
3713
+ description: 'Language code',
3714
+ example: 'en'
3562
3715
  },
3563
- updatedAt: {
3564
- format: 'date-time',
3716
+ locale: {
3565
3717
  type: 'string',
3566
- description: 'Updated at timestamp'
3567
- },
3568
- pendingCount: {
3569
- type: 'number',
3570
- description: 'Number of pending expected transactions'
3571
- },
3572
- overdueCount: {
3573
- type: 'number',
3574
- description: 'Number of overdue expected transactions'
3575
- },
3576
- nextExpectedDate: {
3577
- type: 'object',
3578
- description: 'Next expected date (YYYY-MM-DD)'
3579
- },
3580
- totalAmount: {
3581
- type: 'number',
3582
- description: 'Total amount of all matched transactions'
3583
- },
3584
- averageAmount: {
3585
- type: 'number',
3586
- description: 'Average amount per transaction'
3718
+ description: 'Locale code',
3719
+ example: 'en-US'
3587
3720
  },
3588
- transactionCount: {
3721
+ projectedTotalAmount: {
3589
3722
  type: 'number',
3590
- description: 'Number of matched transactions'
3591
- },
3592
- firstDate: {
3593
- type: 'object',
3594
- description: 'First matched transaction date (YYYY-MM-DD)'
3723
+ description: 'Projected total amount',
3724
+ example: 1000000
3595
3725
  },
3596
- lastDate: {
3597
- type: 'object',
3598
- description: 'Last matched transaction date (YYYY-MM-DD)'
3726
+ retirementDate: {
3727
+ type: 'string',
3728
+ description: 'Retirement date in ISO 8601 format',
3729
+ example: '2050-01-01'
3599
3730
  },
3600
- variance: {
3731
+ savingsRate: {
3601
3732
  type: 'number',
3602
- description: 'Amount variance (standard deviation squared)'
3733
+ description: 'Savings rate percentage',
3734
+ example: 0.2
3603
3735
  },
3604
- upcomingCount: {
3605
- type: 'number',
3606
- description: 'Number of upcoming expected transactions'
3736
+ viewMode: {
3737
+ type: 'string',
3738
+ description: 'View mode',
3739
+ enum: ['DEFAULT', 'ZEN']
3740
+ }
3741
+ }
3742
+ } as const;
3743
+
3744
+ export const $UpdatePropertyDto = {
3745
+ type: 'object',
3746
+ properties: {
3747
+ value: {
3748
+ type: 'string',
3749
+ description: 'Property value'
3607
3750
  }
3608
3751
  },
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
- ]
3752
+ required: ['value']
3631
3753
  } as const;
3632
3754
 
3633
- export const $UpdateRecurringRuleDto = {
3755
+ export const $CreateRecurringRuleDto = {
3634
3756
  type: 'object',
3635
3757
  properties: {
3636
3758
  name: {
3637
3759
  type: 'string',
3638
- description: 'Rule name',
3760
+ description: 'Rule name (unique per user)',
3639
3761
  maxLength: 100
3640
3762
  },
3641
3763
  icon: {
@@ -3658,7 +3780,7 @@ export const $UpdateRecurringRuleDto = {
3658
3780
  },
3659
3781
  expectedAmount: {
3660
3782
  type: 'number',
3661
- description: 'Expected amount',
3783
+ description: 'Expected amount (positive number)',
3662
3784
  minimum: 0
3663
3785
  },
3664
3786
  expectedDay: {
@@ -3669,7 +3791,7 @@ export const $UpdateRecurringRuleDto = {
3669
3791
  },
3670
3792
  customIntervalDays: {
3671
3793
  type: 'number',
3672
- description: 'Custom interval in days',
3794
+ description: 'Custom interval in days (required for CUSTOM frequency)',
3673
3795
  minimum: 1
3674
3796
  },
3675
3797
  currency: {
@@ -3679,118 +3801,136 @@ export const $UpdateRecurringRuleDto = {
3679
3801
  },
3680
3802
  matchPayeePattern: {
3681
3803
  type: 'string',
3682
- description: 'Payee matching pattern',
3804
+ description: 'Payee matching pattern (supports wildcards)',
3683
3805
  maxLength: 200
3684
3806
  },
3685
3807
  matchAmountTolerance: {
3686
3808
  type: 'number',
3687
3809
  description: 'Amount tolerance percentage (0-1)',
3810
+ default: 0.075,
3688
3811
  minimum: 0,
3689
3812
  maximum: 1
3690
3813
  },
3691
3814
  defaultExpenseAccount: {
3692
3815
  type: 'string',
3693
- description: 'Default expense account',
3816
+ description: 'Default expense account for auto-create',
3694
3817
  maxLength: 200
3695
3818
  },
3696
3819
  defaultPaymentAccount: {
3697
3820
  type: 'string',
3698
- description: 'Default payment account',
3821
+ description: 'Default payment account for auto-create',
3699
3822
  maxLength: 200
3700
3823
  },
3701
3824
  defaultPayee: {
3702
3825
  type: 'string',
3703
- description: 'Default payee',
3826
+ description: 'Default payee for auto-create',
3704
3827
  maxLength: 200
3705
3828
  },
3706
3829
  autoCreate: {
3707
3830
  type: 'boolean',
3708
- description: 'Auto-create transaction'
3831
+ description: 'Auto-create transaction when expected date arrives',
3832
+ default: false
3709
3833
  },
3710
- isActive: {
3711
- type: 'boolean',
3712
- description: 'Rule active status'
3834
+ startDate: {
3835
+ type: 'string',
3836
+ description: 'Rule start date (ISO format)'
3713
3837
  },
3714
3838
  endDate: {
3715
3839
  type: 'string',
3716
3840
  description: 'Rule end date (ISO format)'
3717
3841
  }
3718
- }
3842
+ },
3843
+ required: [
3844
+ 'name',
3845
+ 'frequency',
3846
+ 'expectedAmount',
3847
+ 'matchAmountTolerance',
3848
+ 'autoCreate'
3849
+ ]
3719
3850
  } as const;
3720
3851
 
3721
- export const $ExpectedTransactionRuleDto = {
3852
+ export const $RecurringRuleResponseDto = {
3722
3853
  type: 'object',
3723
3854
  properties: {
3855
+ id: {
3856
+ type: 'string',
3857
+ description: 'Rule ID'
3858
+ },
3859
+ userId: {
3860
+ type: 'string',
3861
+ description: 'User ID'
3862
+ },
3724
3863
  name: {
3725
3864
  type: 'string',
3726
3865
  description: 'Rule name'
3727
3866
  },
3728
3867
  icon: {
3729
- type: 'object',
3730
- description: 'Rule icon'
3868
+ type: 'string',
3869
+ description: 'Icon emoji'
3731
3870
  },
3732
3871
  frequency: {
3733
3872
  type: 'string',
3734
- description: 'Rule frequency'
3873
+ description: 'Recurring frequency'
3874
+ },
3875
+ expectedAmount: {
3876
+ type: 'number',
3877
+ description: 'Expected amount'
3878
+ },
3879
+ expectedDay: {
3880
+ type: 'number',
3881
+ description: 'Expected day of month'
3882
+ },
3883
+ customIntervalDays: {
3884
+ type: 'number',
3885
+ description: 'Custom interval in days'
3735
3886
  },
3736
3887
  currency: {
3737
3888
  type: 'string',
3738
3889
  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: {
3748
- type: 'string',
3749
- description: 'Expected transaction ID'
3750
3890
  },
3751
- userId: {
3891
+ matchPayeePattern: {
3752
3892
  type: 'string',
3753
- description: 'User ID'
3893
+ description: 'Payee matching pattern'
3754
3894
  },
3755
- ruleId: {
3756
- type: 'string',
3757
- description: 'Associated rule ID'
3895
+ matchAmountTolerance: {
3896
+ type: 'number',
3897
+ description: 'Amount tolerance percentage'
3758
3898
  },
3759
- expectedDate: {
3899
+ defaultExpenseAccount: {
3760
3900
  type: 'string',
3761
- description: 'Expected date (YYYY-MM-DD)'
3901
+ description: 'Default expense account'
3762
3902
  },
3763
- expectedAmount: {
3764
- type: 'number',
3765
- description: 'Expected amount'
3903
+ defaultPaymentAccount: {
3904
+ type: 'string',
3905
+ description: 'Default payment account'
3766
3906
  },
3767
- status: {
3907
+ defaultPayee: {
3768
3908
  type: 'string',
3769
- description: 'Status (PENDING, COMPLETED, SKIPPED)'
3909
+ description: 'Default payee'
3770
3910
  },
3771
- matchedTransactionId: {
3772
- type: 'object',
3773
- description: 'Matched transaction ID'
3911
+ isActive: {
3912
+ type: 'boolean',
3913
+ description: 'Whether rule is active'
3774
3914
  },
3775
- matchedAt: {
3776
- type: 'object',
3777
- description: 'Match timestamp (ISO 8601)'
3915
+ startDate: {
3916
+ type: 'string',
3917
+ description: 'Rule start date (YYYY-MM-DD)'
3778
3918
  },
3779
- matchConfidence: {
3780
- type: 'object',
3781
- description: 'Match confidence score (0-1)'
3919
+ endDate: {
3920
+ type: 'string',
3921
+ description: 'Rule end date (YYYY-MM-DD)'
3782
3922
  },
3783
- isOverdue: {
3923
+ autoCreate: {
3784
3924
  type: 'boolean',
3785
- description: 'Whether this expected transaction is overdue'
3925
+ description: 'Auto-create transaction on expected date'
3786
3926
  },
3787
- rule: {
3788
- description: 'Rule information',
3789
- allOf: [
3790
- {
3791
- $ref: '#/components/schemas/ExpectedTransactionRuleDto'
3792
- }
3793
- ]
3927
+ lastOccurrence: {
3928
+ type: 'string',
3929
+ description: 'Last matched occurrence date (YYYY-MM-DD)'
3930
+ },
3931
+ totalCount: {
3932
+ type: 'number',
3933
+ description: 'Total matched transactions count'
3794
3934
  },
3795
3935
  createdAt: {
3796
3936
  format: 'date-time',
@@ -3806,691 +3946,581 @@ export const $ExpectedTransactionResponseDto = {
3806
3946
  required: [
3807
3947
  'id',
3808
3948
  'userId',
3809
- 'ruleId',
3810
- 'expectedDate',
3949
+ 'name',
3950
+ 'frequency',
3811
3951
  'expectedAmount',
3812
- 'status',
3813
- 'isOverdue',
3814
- 'rule',
3952
+ 'currency',
3953
+ 'matchAmountTolerance',
3954
+ 'isActive',
3955
+ 'startDate',
3956
+ 'autoCreate',
3957
+ 'totalCount',
3815
3958
  'createdAt',
3816
3959
  'updatedAt'
3817
3960
  ]
3818
3961
  } as const;
3819
3962
 
3820
- export const $ExpectedTransactionListResponseDto = {
3963
+ export const $CreateRuleFromTransactionDto = {
3821
3964
  type: 'object',
3822
3965
  properties: {
3823
- items: {
3824
- type: 'array',
3825
- items: {
3826
- $ref: '#/components/schemas/ExpectedTransactionResponseDto'
3827
- }
3966
+ frequency: {
3967
+ type: 'string',
3968
+ description: 'Recurring frequency',
3969
+ enum: [
3970
+ 'WEEKLY',
3971
+ 'BIWEEKLY',
3972
+ 'MONTHLY',
3973
+ 'BIMONTHLY',
3974
+ 'QUARTERLY',
3975
+ 'YEARLY',
3976
+ 'CUSTOM'
3977
+ ],
3978
+ example: 'MONTHLY'
3828
3979
  },
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: {
3980
+ name: {
3841
3981
  type: 'string',
3842
- description: 'Transaction ID to match with'
3982
+ description: 'Optional name override (default: transaction payee)',
3983
+ maxLength: 100
3984
+ },
3985
+ icon: {
3986
+ type: 'string',
3987
+ description: 'Optional icon emoji',
3988
+ maxLength: 10
3843
3989
  }
3844
3990
  },
3845
- required: ['transactionId']
3991
+ required: ['frequency']
3846
3992
  } as const;
3847
3993
 
3848
- export const $EnterNowDto = {
3994
+ export const $RecurringRuleWithStatsResponseDto = {
3849
3995
  type: 'object',
3850
3996
  properties: {
3851
- expenseAccount: {
3997
+ id: {
3852
3998
  type: 'string',
3853
- description:
3854
- 'Override expense account (uses rule default if not provided)',
3855
- maxLength: 200
3999
+ description: 'Rule ID'
3856
4000
  },
3857
- paymentAccount: {
4001
+ userId: {
3858
4002
  type: 'string',
3859
- description:
3860
- 'Override payment account (uses rule default if not provided)',
3861
- maxLength: 200
4003
+ description: 'User ID'
3862
4004
  },
3863
- amount: {
3864
- type: 'number',
3865
- description: 'Override amount (uses expected amount if not provided)',
3866
- minimum: 0
4005
+ name: {
4006
+ type: 'string',
4007
+ description: 'Rule name'
3867
4008
  },
3868
- payee: {
4009
+ icon: {
3869
4010
  type: 'string',
3870
- description: 'Override payee (uses rule default if not provided)',
3871
- maxLength: 200
4011
+ description: 'Icon emoji'
3872
4012
  },
3873
- narration: {
4013
+ frequency: {
3874
4014
  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: {
4015
+ description: 'Recurring frequency'
4016
+ },
4017
+ expectedAmount: {
4018
+ type: 'number',
4019
+ description: 'Expected amount'
4020
+ },
4021
+ expectedDay: {
4022
+ type: 'number',
4023
+ description: 'Expected day of month'
4024
+ },
4025
+ customIntervalDays: {
4026
+ type: 'number',
4027
+ description: 'Custom interval in days'
4028
+ },
4029
+ currency: {
3885
4030
  type: 'string',
3886
- description: 'Rule name',
3887
- example: 'Rent'
4031
+ description: 'Currency code'
3888
4032
  },
3889
- ruleId: {
4033
+ matchPayeePattern: {
3890
4034
  type: 'string',
3891
- description: 'Rule ID',
3892
- example: 'clx123...'
4035
+ description: 'Payee matching pattern'
3893
4036
  },
3894
- amount: {
4037
+ matchAmountTolerance: {
3895
4038
  type: 'number',
3896
- description: 'Expected amount',
3897
- example: 3000
4039
+ description: 'Amount tolerance percentage'
3898
4040
  },
3899
- date: {
4041
+ defaultExpenseAccount: {
3900
4042
  type: 'string',
3901
- description: 'Expected date (YYYY-MM-DD)',
3902
- example: '2024-04-01'
4043
+ description: 'Default expense account'
3903
4044
  },
3904
- icon: {
4045
+ defaultPaymentAccount: {
3905
4046
  type: 'string',
3906
- description: 'Rule icon emoji',
3907
- example: '🏠',
3908
- nullable: true
4047
+ description: 'Default payment account'
3909
4048
  },
3910
- currency: {
4049
+ defaultPayee: {
3911
4050
  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: {
4051
+ description: 'Default payee'
4052
+ },
4053
+ isActive: {
4054
+ type: 'boolean',
4055
+ description: 'Whether rule is active'
4056
+ },
4057
+ startDate: {
3923
4058
  type: 'string',
3924
- description: 'Month (YYYY-MM)',
3925
- example: '2024-04'
4059
+ description: 'Rule start date (YYYY-MM-DD)'
3926
4060
  },
3927
- expectedOutflow: {
4061
+ endDate: {
4062
+ type: 'string',
4063
+ description: 'Rule end date (YYYY-MM-DD)'
4064
+ },
4065
+ autoCreate: {
4066
+ type: 'boolean',
4067
+ description: 'Auto-create transaction on expected date'
4068
+ },
4069
+ lastOccurrence: {
4070
+ type: 'string',
4071
+ description: 'Last matched occurrence date (YYYY-MM-DD)'
4072
+ },
4073
+ totalCount: {
3928
4074
  type: 'number',
3929
- description: 'Total expected outflow for the month',
3930
- example: 8500
4075
+ description: 'Total matched transactions count'
3931
4076
  },
3932
- itemCount: {
4077
+ createdAt: {
4078
+ format: 'date-time',
4079
+ type: 'string',
4080
+ description: 'Created at timestamp'
4081
+ },
4082
+ updatedAt: {
4083
+ format: 'date-time',
4084
+ type: 'string',
4085
+ description: 'Updated at timestamp'
4086
+ },
4087
+ pendingCount: {
3933
4088
  type: 'number',
3934
- description: 'Number of expected transactions',
3935
- example: 3
4089
+ description: 'Number of pending expected transactions'
3936
4090
  },
3937
- byCurrency: {
3938
- type: 'object',
3939
- description: 'Breakdown by currency',
3940
- example: {
3941
- CNY: 8500,
3942
- USD: 100
3943
- }
4091
+ overdueCount: {
4092
+ type: 'number',
4093
+ description: 'Number of overdue expected transactions'
3944
4094
  },
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
- }
4095
+ nextExpectedDate: {
4096
+ type: 'string',
4097
+ description: 'Next expected date (YYYY-MM-DD)'
3965
4098
  },
3966
- totalOutflow: {
4099
+ totalAmount: {
3967
4100
  type: 'number',
3968
- description: 'Total expected outflow across all months',
3969
- example: 25500
4101
+ description: 'Total amount of all matched transactions'
3970
4102
  },
3971
- totalByCurrency: {
3972
- type: 'object',
3973
- description: 'Total by currency across all months',
3974
- example: {
3975
- CNY: 25500,
3976
- USD: 300
3977
- }
4103
+ averageAmount: {
4104
+ type: 'number',
4105
+ description: 'Average amount per transaction'
3978
4106
  },
3979
- rulesCount: {
4107
+ transactionCount: {
3980
4108
  type: 'number',
3981
- description: 'Number of active recurring rules included',
3982
- example: 5
4109
+ description: 'Number of matched transactions'
3983
4110
  },
3984
- periodStart: {
4111
+ firstDate: {
3985
4112
  type: 'string',
3986
- description: 'Forecast period start date',
3987
- example: '2024-04-01'
4113
+ description: 'First matched transaction date (YYYY-MM-DD)'
3988
4114
  },
3989
- periodEnd: {
4115
+ lastDate: {
3990
4116
  type: 'string',
3991
- description: 'Forecast period end date',
3992
- example: '2024-06-30'
4117
+ description: 'Last matched transaction date (YYYY-MM-DD)'
4118
+ },
4119
+ variance: {
4120
+ type: 'number',
4121
+ description: 'Amount variance (standard deviation squared)'
4122
+ },
4123
+ upcomingCount: {
4124
+ type: 'number',
4125
+ description: 'Number of upcoming expected transactions'
3993
4126
  }
3994
4127
  },
3995
4128
  required: [
3996
- 'forecast',
3997
- 'totalOutflow',
3998
- 'totalByCurrency',
3999
- 'rulesCount',
4000
- 'periodStart',
4001
- 'periodEnd'
4129
+ 'id',
4130
+ 'userId',
4131
+ 'name',
4132
+ 'frequency',
4133
+ 'expectedAmount',
4134
+ 'currency',
4135
+ 'matchAmountTolerance',
4136
+ 'isActive',
4137
+ 'startDate',
4138
+ 'autoCreate',
4139
+ 'totalCount',
4140
+ 'createdAt',
4141
+ 'updatedAt',
4142
+ 'pendingCount',
4143
+ 'overdueCount',
4144
+ 'totalAmount',
4145
+ 'averageAmount',
4146
+ 'transactionCount',
4147
+ 'variance',
4148
+ 'upcomingCount'
4002
4149
  ]
4003
4150
  } as const;
4004
4151
 
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'
4029
- },
4030
- value: {
4031
- type: 'string',
4032
- description: 'Value at this date (in base currency)',
4033
- example: '500000.00'
4034
- },
4035
- change: {
4036
- type: 'object',
4037
- description: 'Change from previous point',
4038
- example: '5000.00'
4039
- },
4040
- assets: {
4041
- type: 'string',
4042
- description: 'Total assets at this date (in base currency)',
4043
- example: '494338.00'
4044
- },
4045
- liabilities: {
4046
- type: 'string',
4047
- description: 'Total liabilities at this date (in base currency)',
4048
- example: '310098.00'
4049
- },
4050
- byCurrency: {
4051
- description: 'Multi-currency breakdown for this point',
4052
- type: 'array',
4053
- items: {
4054
- $ref: '#/components/schemas/CurrencyBalanceDto'
4055
- }
4056
- }
4057
- },
4058
- required: ['date', 'value']
4059
- } as const;
4060
-
4061
- export const $TrendSummaryDto = {
4152
+ export const $UpdateRecurringRuleDto = {
4062
4153
  type: 'object',
4063
4154
  properties: {
4064
- startValue: {
4065
- type: 'string',
4066
- description: 'Value at start of period',
4067
- example: '450000.00'
4068
- },
4069
- endValue: {
4155
+ name: {
4070
4156
  type: 'string',
4071
- description: 'Value at end of period',
4072
- example: '500000.00'
4157
+ description: 'Rule name (unique per user)',
4158
+ maxLength: 100
4073
4159
  },
4074
- totalChange: {
4160
+ icon: {
4075
4161
  type: 'string',
4076
- description: 'Total change over period',
4077
- example: '50000.00'
4162
+ description: 'Icon emoji',
4163
+ maxLength: 10
4078
4164
  },
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: {
4165
+ frequency: {
4092
4166
  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
- }
4167
+ description: 'Recurring frequency',
4168
+ enum: [
4169
+ 'WEEKLY',
4170
+ 'BIWEEKLY',
4171
+ 'MONTHLY',
4172
+ 'BIMONTHLY',
4173
+ 'QUARTERLY',
4174
+ 'YEARLY',
4175
+ 'CUSTOM'
4123
4176
  ]
4124
4177
  },
4125
- period: {
4126
- type: 'string',
4127
- description: 'Period requested',
4128
- example: '6m'
4178
+ expectedAmount: {
4179
+ type: 'number',
4180
+ description: 'Expected amount (positive number)',
4181
+ minimum: 0
4129
4182
  },
4130
- granularity: {
4131
- type: 'string',
4132
- description: 'Data granularity',
4133
- example: 'month'
4183
+ expectedDay: {
4184
+ type: 'number',
4185
+ description: 'Expected day of month (1-31)',
4186
+ minimum: 1,
4187
+ maximum: 31
4134
4188
  },
4135
4189
  currency: {
4136
4190
  type: 'string',
4137
- description: 'Base currency for converted values',
4138
- example: 'CNY'
4139
- },
4140
- byCurrency: {
4141
- description:
4142
- 'Multi-currency time series (each point has currency breakdown)',
4143
- type: 'array',
4144
- items: {
4145
- $ref: '#/components/schemas/MultiCurrencyPointDto'
4146
- }
4147
- },
4148
- warnings: {
4149
- description: 'Exchange rate warnings',
4150
- type: 'array',
4151
- items: {
4152
- $ref: '#/components/schemas/ExchangeRateWarningDto'
4153
- }
4154
- }
4155
- },
4156
- required: ['series', 'summary', 'period', 'granularity', 'currency']
4157
- } as const;
4158
-
4159
- export const $CashFlowPointDto = {
4160
- type: 'object',
4161
- properties: {
4162
- month: {
4163
- type: 'string',
4164
- description: 'Month key (YYYY-MM)',
4165
- example: '2024-03'
4166
- },
4167
- income: {
4168
- type: 'string',
4169
- description: 'Income in base currency (absolute, converted)',
4170
- example: '10000.00'
4171
- },
4172
- expense: {
4173
- type: 'string',
4174
- description: 'Expense in base currency (absolute, converted)',
4175
- example: '5000.00'
4191
+ description: 'Currency code',
4192
+ maxLength: 10
4176
4193
  },
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: {
4194
+ matchPayeePattern: {
4190
4195
  type: 'string',
4191
- description: 'Total income across the period',
4192
- example: '60000.00'
4196
+ description: 'Payee matching pattern (supports wildcards)',
4197
+ maxLength: 200
4193
4198
  },
4194
- totalExpense: {
4195
- type: 'string',
4196
- description: 'Total expense across the period',
4197
- example: '30000.00'
4199
+ matchAmountTolerance: {
4200
+ type: 'number',
4201
+ description: 'Amount tolerance percentage (0-1)',
4202
+ default: 0.075,
4203
+ minimum: 0,
4204
+ maximum: 1
4198
4205
  },
4199
- totalNetSavings: {
4206
+ defaultExpenseAccount: {
4200
4207
  type: 'string',
4201
- description: 'income expense across the period',
4202
- example: '30000.00'
4208
+ description: 'Default expense account for auto-create',
4209
+ maxLength: 200
4203
4210
  },
4204
- averageMonthlyNetSavings: {
4211
+ defaultPaymentAccount: {
4205
4212
  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
- ]
4213
+ description: 'Default payment account for auto-create',
4214
+ maxLength: 200
4237
4215
  },
4238
- period: {
4216
+ defaultPayee: {
4239
4217
  type: 'string',
4240
- description: 'Period requested',
4241
- example: '6m'
4218
+ description: 'Default payee for auto-create',
4219
+ maxLength: 200
4242
4220
  },
4243
- granularity: {
4244
- type: 'string',
4245
- description: 'Data granularity (v1 returns month buckets)',
4246
- example: 'month'
4221
+ autoCreate: {
4222
+ type: 'boolean',
4223
+ description: 'Auto-create transaction when expected date arrives',
4224
+ default: false
4247
4225
  },
4248
- currency: {
4226
+ endDate: {
4249
4227
  type: 'string',
4250
- description: 'Base currency for converted values',
4251
- example: 'CNY'
4228
+ description: 'Rule end date (ISO format)'
4252
4229
  },
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'
4230
+ customIntervalDays: {
4231
+ type: 'number',
4232
+ description: 'Custom interval in days',
4233
+ minimum: 1
4234
+ },
4235
+ isActive: {
4236
+ type: 'boolean',
4237
+ description: 'Rule active status'
4291
4238
  }
4292
- },
4293
- required: ['accessToken']
4239
+ }
4294
4240
  } as const;
4295
4241
 
4296
- export const $UserSettingsResponseDto = {
4242
+ export const $ExpectedTransactionRuleDto = {
4297
4243
  type: 'object',
4298
4244
  properties: {
4299
- baseCurrency: {
4245
+ name: {
4300
4246
  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
4247
+ description: 'Rule name'
4248
+ },
4249
+ icon: {
4250
+ type: 'string',
4251
+ description: 'Rule icon'
4252
+ },
4253
+ frequency: {
4254
+ type: 'string',
4255
+ description: 'Rule frequency'
4256
+ },
4257
+ currency: {
4258
+ type: 'string',
4259
+ description: 'Currency code'
4305
4260
  }
4306
4261
  },
4307
- required: ['baseCurrency']
4262
+ required: ['name', 'frequency', 'currency']
4308
4263
  } as const;
4309
4264
 
4310
- export const $UserResponseDto = {
4265
+ export const $ExpectedTransactionResponseDto = {
4311
4266
  type: 'object',
4312
4267
  properties: {
4313
4268
  id: {
4269
+ type: 'string',
4270
+ description: 'Expected transaction ID'
4271
+ },
4272
+ userId: {
4314
4273
  type: 'string',
4315
4274
  description: 'User ID'
4316
4275
  },
4317
- role: {
4276
+ ruleId: {
4318
4277
  type: 'string',
4319
- description: 'Assigned user role'
4278
+ description: 'Associated rule ID'
4320
4279
  },
4321
- permissions: {
4322
- description: 'Permission strings',
4323
- type: 'array',
4324
- items: {
4325
- type: 'string'
4326
- }
4280
+ expectedDate: {
4281
+ type: 'string',
4282
+ description: 'Expected date (YYYY-MM-DD)'
4327
4283
  },
4328
- settings: {
4329
- description: 'User settings',
4284
+ expectedAmount: {
4285
+ type: 'number',
4286
+ description: 'Expected amount'
4287
+ },
4288
+ status: {
4289
+ type: 'string',
4290
+ description: 'Status (PENDING, COMPLETED, SKIPPED)'
4291
+ },
4292
+ matchedTransactionId: {
4293
+ type: 'string',
4294
+ description: 'Matched transaction ID'
4295
+ },
4296
+ matchedAt: {
4297
+ type: 'string',
4298
+ description: 'Match timestamp (ISO 8601)'
4299
+ },
4300
+ matchConfidence: {
4301
+ type: 'number',
4302
+ description: 'Match confidence score (0-1)'
4303
+ },
4304
+ isOverdue: {
4305
+ type: 'boolean',
4306
+ description: 'Whether this expected transaction is overdue'
4307
+ },
4308
+ rule: {
4309
+ description: 'Rule information',
4330
4310
  allOf: [
4331
4311
  {
4332
- $ref: '#/components/schemas/UserSettingsResponseDto'
4312
+ $ref: '#/components/schemas/ExpectedTransactionRuleDto'
4333
4313
  }
4334
4314
  ]
4315
+ },
4316
+ createdAt: {
4317
+ format: 'date-time',
4318
+ type: 'string',
4319
+ description: 'Created at timestamp'
4320
+ },
4321
+ updatedAt: {
4322
+ format: 'date-time',
4323
+ type: 'string',
4324
+ description: 'Updated at timestamp'
4335
4325
  }
4336
4326
  },
4337
- required: ['id', 'role', 'permissions', 'settings']
4327
+ required: [
4328
+ 'id',
4329
+ 'userId',
4330
+ 'ruleId',
4331
+ 'expectedDate',
4332
+ 'expectedAmount',
4333
+ 'status',
4334
+ 'isOverdue',
4335
+ 'rule',
4336
+ 'createdAt',
4337
+ 'updatedAt'
4338
+ ]
4338
4339
  } as const;
4339
4340
 
4340
- export const $SignupDto = {
4341
+ export const $ExpectedTransactionListResponseDto = {
4341
4342
  type: 'object',
4342
4343
  properties: {
4343
- turnstileToken: {
4344
+ items: {
4345
+ type: 'array',
4346
+ items: {
4347
+ $ref: '#/components/schemas/ExpectedTransactionResponseDto'
4348
+ }
4349
+ },
4350
+ total: {
4351
+ type: 'number',
4352
+ description: 'Total count'
4353
+ }
4354
+ },
4355
+ required: ['items', 'total']
4356
+ } as const;
4357
+
4358
+ export const $ConfirmMatchDto = {
4359
+ type: 'object',
4360
+ properties: {
4361
+ transactionId: {
4344
4362
  type: 'string',
4345
- description:
4346
- 'Cloudflare Turnstile verification token (optional when Turnstile disabled)',
4347
- example: '0.abc123def456...'
4363
+ description: 'Transaction ID to match with'
4348
4364
  }
4349
- }
4365
+ },
4366
+ required: ['transactionId']
4350
4367
  } as const;
4351
4368
 
4352
- export const $SignupResponseDto = {
4369
+ export const $EnterNowDto = {
4353
4370
  type: 'object',
4354
4371
  properties: {
4355
- authToken: {
4372
+ expenseAccount: {
4356
4373
  type: 'string',
4357
- description: 'JWT auth token',
4358
- example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...'
4374
+ description:
4375
+ 'Override expense account (uses rule default if not provided)',
4376
+ maxLength: 200
4359
4377
  },
4360
- accessToken: {
4378
+ paymentAccount: {
4361
4379
  type: 'string',
4362
- description: 'Auto-generated access token'
4380
+ description:
4381
+ 'Override payment account (uses rule default if not provided)',
4382
+ maxLength: 200
4363
4383
  },
4364
- role: {
4384
+ amount: {
4385
+ type: 'number',
4386
+ description: 'Override amount (uses expected amount if not provided)',
4387
+ minimum: 0
4388
+ },
4389
+ payee: {
4365
4390
  type: 'string',
4366
- description: 'Assigned user role',
4367
- enum: ['USER', 'ADMIN', 'DEMO', 'INACTIVE', 'PAID', 'OPS']
4391
+ description: 'Override payee (uses rule default if not provided)',
4392
+ maxLength: 200
4393
+ },
4394
+ narration: {
4395
+ type: 'string',
4396
+ description: 'Optional narration',
4397
+ maxLength: 500
4368
4398
  }
4369
- },
4370
- required: ['authToken', 'accessToken', 'role']
4399
+ }
4371
4400
  } as const;
4372
4401
 
4373
- export const $UpdateUserSettingDto = {
4402
+ export const $ForecastItemDto = {
4374
4403
  type: 'object',
4375
4404
  properties: {
4376
- secId: {
4377
- type: 'number',
4378
- description: 'Security ID'
4405
+ rule: {
4406
+ type: 'string',
4407
+ description: 'Rule name',
4408
+ example: 'Rent'
4379
4409
  },
4380
- annualInterestRate: {
4410
+ ruleId: {
4411
+ type: 'string',
4412
+ description: 'Rule ID',
4413
+ example: 'clx123...'
4414
+ },
4415
+ amount: {
4381
4416
  type: 'number',
4382
- description: 'Annual interest rate',
4383
- example: 0.05
4417
+ description: 'Expected amount',
4418
+ example: 3000
4384
4419
  },
4385
- currency: {
4420
+ date: {
4386
4421
  type: 'string',
4387
- description: 'Currency code',
4388
- example: 'USD'
4422
+ description: 'Expected date (YYYY-MM-DD)',
4423
+ example: '2024-04-01'
4389
4424
  },
4390
- baseCurrency: {
4425
+ icon: {
4391
4426
  type: 'string',
4392
- description: 'Base currency code',
4393
- example: 'USD'
4427
+ description: 'Rule icon emoji',
4428
+ example: '🏠',
4429
+ nullable: true
4394
4430
  },
4395
- benchmark: {
4431
+ currency: {
4396
4432
  type: 'string',
4397
- description: 'Benchmark symbol',
4398
- example: 'SPY'
4399
- },
4400
- colorScheme: {
4433
+ description: 'Currency code',
4434
+ example: 'CNY'
4435
+ }
4436
+ },
4437
+ required: ['rule', 'ruleId', 'amount', 'date', 'icon', 'currency']
4438
+ } as const;
4439
+
4440
+ export const $MonthlyForecastDto = {
4441
+ type: 'object',
4442
+ properties: {
4443
+ month: {
4401
4444
  type: 'string',
4402
- description: 'Color scheme',
4403
- enum: ['DARK', 'LIGHT']
4445
+ description: 'Month (YYYY-MM)',
4446
+ example: '2024-04'
4404
4447
  },
4405
- dateRange: {
4406
- type: 'string',
4407
- description: 'Date range filter',
4408
- example: '1y'
4448
+ expectedOutflow: {
4449
+ type: 'number',
4450
+ description: 'Total expected outflow for the month',
4451
+ example: 8500
4409
4452
  },
4410
- emergencyFund: {
4453
+ itemCount: {
4411
4454
  type: 'number',
4412
- description: 'Emergency fund amount',
4413
- example: 10000
4455
+ description: 'Number of expected transactions',
4456
+ example: 3
4414
4457
  },
4415
- 'filters.accounts': {
4416
- description: 'Account filter IDs',
4458
+ byCurrency: {
4459
+ type: 'object',
4460
+ description: 'Breakdown by currency',
4461
+ example: {
4462
+ CNY: 8500,
4463
+ USD: 100
4464
+ }
4465
+ },
4466
+ items: {
4467
+ description: 'Individual forecast items',
4417
4468
  type: 'array',
4418
4469
  items: {
4419
- type: 'string'
4470
+ $ref: '#/components/schemas/ForecastItemDto'
4420
4471
  }
4421
- },
4422
- 'filters.assetClasses': {
4423
- description: 'Asset class filters',
4472
+ }
4473
+ },
4474
+ required: ['month', 'expectedOutflow', 'itemCount', 'byCurrency', 'items']
4475
+ } as const;
4476
+
4477
+ export const $ForecastResponseDto = {
4478
+ type: 'object',
4479
+ properties: {
4480
+ forecast: {
4481
+ description: 'Monthly forecast data',
4424
4482
  type: 'array',
4425
4483
  items: {
4426
- type: 'string'
4484
+ $ref: '#/components/schemas/MonthlyForecastDto'
4427
4485
  }
4428
4486
  },
4429
- 'filters.dataSource': {
4430
- type: 'string',
4431
- description: 'Data source filter'
4432
- },
4433
- 'filters.symbol': {
4434
- type: 'string',
4435
- description: 'Symbol filter'
4487
+ totalOutflow: {
4488
+ type: 'number',
4489
+ description: 'Total expected outflow across all months',
4490
+ example: 25500
4436
4491
  },
4437
- 'filters.tags': {
4438
- description: 'Tag filters',
4439
- type: 'array',
4440
- items: {
4441
- type: 'string'
4492
+ totalByCurrency: {
4493
+ type: 'object',
4494
+ description: 'Total by currency across all months',
4495
+ example: {
4496
+ CNY: 25500,
4497
+ USD: 300
4442
4498
  }
4443
4499
  },
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: {
4500
+ rulesCount: {
4463
4501
  type: 'number',
4464
- description: 'Projected total amount',
4465
- example: 1000000
4502
+ description: 'Number of active recurring rules included',
4503
+ example: 5
4466
4504
  },
4467
- retirementDate: {
4505
+ periodStart: {
4468
4506
  type: 'string',
4469
- description: 'Retirement date in ISO 8601 format',
4470
- example: '2050-01-01'
4471
- },
4472
- savingsRate: {
4473
- type: 'number',
4474
- description: 'Savings rate percentage',
4475
- example: 0.2
4507
+ description: 'Forecast period start date',
4508
+ example: '2024-04-01'
4476
4509
  },
4477
- viewMode: {
4478
- type: 'string',
4479
- description: 'View mode',
4480
- enum: ['DEFAULT', 'ZEN']
4481
- }
4482
- }
4483
- } as const;
4484
-
4485
- export const $UpdatePropertyDto = {
4486
- type: 'object',
4487
- properties: {
4488
- value: {
4510
+ periodEnd: {
4489
4511
  type: 'string',
4490
- description: 'Property value'
4512
+ description: 'Forecast period end date',
4513
+ example: '2024-06-30'
4491
4514
  }
4492
4515
  },
4493
- required: ['value']
4516
+ required: [
4517
+ 'forecast',
4518
+ 'totalOutflow',
4519
+ 'totalByCurrency',
4520
+ 'rulesCount',
4521
+ 'periodStart',
4522
+ 'periodEnd'
4523
+ ]
4494
4524
  } as const;
4495
4525
 
4496
4526
  export const $CreateTransactionRuleDto = {
@@ -5052,7 +5082,8 @@ export const $UpdateTransactionRuleDto = {
5052
5082
  },
5053
5083
  matchLogic: {
5054
5084
  type: 'string',
5055
- enum: ['OR', 'AND']
5085
+ enum: ['OR', 'AND'],
5086
+ default: 'OR'
5056
5087
  },
5057
5088
  amountMin: {
5058
5089
  type: 'number',
@@ -5066,13 +5097,10 @@ export const $UpdateTransactionRuleDto = {
5066
5097
  },
5067
5098
  priority: {
5068
5099
  type: 'number',
5100
+ default: 50,
5069
5101
  minimum: 0,
5070
5102
  maximum: 1000
5071
5103
  },
5072
- enabled: {
5073
- type: 'boolean',
5074
- description: 'Enable or disable the rule'
5075
- },
5076
5104
  additionalTags: {
5077
5105
  items: {
5078
5106
  type: 'array'
@@ -5082,6 +5110,10 @@ export const $UpdateTransactionRuleDto = {
5082
5110
  },
5083
5111
  additionalMetadata: {
5084
5112
  type: 'object'
5113
+ },
5114
+ enabled: {
5115
+ type: 'boolean',
5116
+ description: 'Enable or disable the rule'
5085
5117
  }
5086
5118
  }
5087
5119
  } as const;
@@ -6387,8 +6419,27 @@ export const $ProcessNlpDto = {
6387
6419
  selectedAccount: {
6388
6420
  type: 'string',
6389
6421
  description:
6390
- '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.',
6422
+ '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
6423
  example: 'Expenses:Food:Coffee'
6424
+ },
6425
+ viewpointAccount: {
6426
+ type: 'string',
6427
+ description:
6428
+ '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.',
6429
+ example: 'Assets:CN:Bank:ICBC'
6430
+ },
6431
+ viewpointCategory: {
6432
+ type: 'string',
6433
+ description:
6434
+ "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.",
6435
+ example: 'Food'
6436
+ },
6437
+ viewpointFlow: {
6438
+ type: 'string',
6439
+ description:
6440
+ "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.",
6441
+ enum: ['income', 'expense'],
6442
+ example: 'expense'
6392
6443
  }
6393
6444
  }
6394
6445
  } as const;
@@ -6702,6 +6753,24 @@ export const $NlpRuleConfirmationDataDto = {
6702
6753
  ]
6703
6754
  } as const;
6704
6755
 
6756
+ export const $NlpAccountCandidateDto = {
6757
+ type: 'object',
6758
+ properties: {
6759
+ path: {
6760
+ type: 'string',
6761
+ description: 'Canonical beancount account path (echo back on selection)',
6762
+ example: 'Expenses:Food:Dining'
6763
+ },
6764
+ name: {
6765
+ type: 'string',
6766
+ description:
6767
+ 'Localized display name (ADR-0114 read-time projection, user locale)',
6768
+ example: '餐饮'
6769
+ }
6770
+ },
6771
+ required: ['path', 'name']
6772
+ } as const;
6773
+
6705
6774
  export const $NlpAccountConfirmationDataDto = {
6706
6775
  type: 'object',
6707
6776
  properties: {
@@ -6717,10 +6786,11 @@ export const $NlpAccountConfirmationDataDto = {
6717
6786
  example: 'Expenses:Food:Drinks'
6718
6787
  },
6719
6788
  similarAccounts: {
6720
- description: 'Similar accounts for user selection',
6789
+ description:
6790
+ 'Similar accounts for user selection (path + localized name, #680)',
6721
6791
  type: 'array',
6722
6792
  items: {
6723
- type: 'string'
6793
+ $ref: '#/components/schemas/NlpAccountCandidateDto'
6724
6794
  }
6725
6795
  },
6726
6796
  errorMessage: {
@@ -7348,6 +7418,79 @@ export const $PlatformMatchResponseDto = {
7348
7418
  required: ['platforms', 'matchType', 'total', 'hasMore']
7349
7419
  } as const;
7350
7420
 
7421
+ export const $PlatformStandardsPlatformDto = {
7422
+ type: 'object',
7423
+ properties: {
7424
+ id: {
7425
+ type: 'string',
7426
+ description: 'Global platform ID'
7427
+ },
7428
+ name: {
7429
+ type: 'string',
7430
+ description: 'Platform name (e.g., "ICBC")'
7431
+ },
7432
+ canonical: {
7433
+ type: 'string',
7434
+ description: 'Canonical identifier in ACCOUNT_RE format (e.g., "icbc")'
7435
+ },
7436
+ suggestedSegment: {
7437
+ type: 'string',
7438
+ description:
7439
+ 'Suggested path segment — canonical PascalCased per hyphen-part, hyphens preserved (e.g. "Apple-Pay")'
7440
+ },
7441
+ type: {
7442
+ type: 'string',
7443
+ description: 'Platform type',
7444
+ enum: [
7445
+ 'BANK',
7446
+ 'BROKERAGE',
7447
+ 'CRYPTO_EXCHANGE',
7448
+ 'PAYMENT',
7449
+ 'INVESTMENT',
7450
+ 'INSURANCE',
7451
+ 'OTHER'
7452
+ ]
7453
+ },
7454
+ category: {
7455
+ type: 'string',
7456
+ description:
7457
+ 'Region-aware category (institution vocab, e.g. DigitalWallet/Bank) resolved against the final region. null = no region-aware suggestion; fall back to type.',
7458
+ nullable: true,
7459
+ example: 'Bank'
7460
+ }
7461
+ },
7462
+ required: ['id', 'name', 'canonical', 'suggestedSegment', 'type', 'category']
7463
+ } as const;
7464
+
7465
+ export const $PlatformStandardsResponseDto = {
7466
+ type: 'object',
7467
+ properties: {
7468
+ platform: {
7469
+ description: 'The selected platform (institution lock source)',
7470
+ allOf: [
7471
+ {
7472
+ $ref: '#/components/schemas/PlatformStandardsPlatformDto'
7473
+ }
7474
+ ]
7475
+ },
7476
+ region: {
7477
+ type: 'string',
7478
+ description:
7479
+ "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.",
7480
+ example: 'CN'
7481
+ },
7482
+ templates: {
7483
+ description:
7484
+ 'Candidate account-standard templates of the resolved region (groupable by productCategory client-side)',
7485
+ type: 'array',
7486
+ items: {
7487
+ $ref: '#/components/schemas/AccountStandardResponseDto'
7488
+ }
7489
+ }
7490
+ },
7491
+ required: ['platform', 'region', 'templates']
7492
+ } as const;
7493
+
7351
7494
  export const $CreatePlatformDto = {
7352
7495
  type: 'object',
7353
7496
  properties: {
@@ -7449,7 +7592,8 @@ export const $UpdatePlatformDto = {
7449
7592
  },
7450
7593
  isActive: {
7451
7594
  type: 'boolean',
7452
- description: 'Whether the platform is active'
7595
+ description: 'Whether the platform is active',
7596
+ default: true
7453
7597
  }
7454
7598
  }
7455
7599
  } as const;
@@ -7648,7 +7792,8 @@ export const $PlatformGroupDto = {
7648
7792
  example: 'CMB Bank'
7649
7793
  },
7650
7794
  accounts: {
7651
- description: 'Accounts within this platform',
7795
+ description:
7796
+ 'Accounts within this platform (Assets and Liabilities rows, #696)',
7652
7797
  type: 'array',
7653
7798
  items: {
7654
7799
  $ref: '#/components/schemas/AccountItemDto'
@@ -7656,7 +7801,8 @@ export const $PlatformGroupDto = {
7656
7801
  },
7657
7802
  totalBalance: {
7658
7803
  type: 'string',
7659
- description: 'FX-converted total balance in base currency',
7804
+ description:
7805
+ 'FX-converted total balance in base currency (nets Assets + Liabilities rows; can be negative)',
7660
7806
  example: '100000.00'
7661
7807
  },
7662
7808
  balanceByCurrency: {
@@ -7675,7 +7821,7 @@ export const $PlatformGroupDto = {
7675
7821
  sharePct: {
7676
7822
  type: 'number',
7677
7823
  description:
7678
- 'Share of the grand converted total (0-100); 0 when grand total is 0',
7824
+ 'Share of the converted asset-side grand total (0-100); liability balances are excluded from the basis; 0 when grand total is 0 (#696)',
7679
7825
  example: 42.5
7680
7826
  }
7681
7827
  },
@@ -7723,7 +7869,8 @@ export const $AccountsSummaryDto = {
7723
7869
  properties: {
7724
7870
  totalAccounts: {
7725
7871
  type: 'number',
7726
- description: 'Total number of accounts'
7872
+ description:
7873
+ 'Total number of accounts (balance sheet: Assets + Liabilities, #696)'
7727
7874
  },
7728
7875
  totalPlatforms: {
7729
7876
  type: 'number',
@@ -8267,7 +8414,7 @@ export const $MonetaryDto = {
8267
8414
  example: 'USD'
8268
8415
  },
8269
8416
  baseCcyEquivalent: {
8270
- type: 'object',
8417
+ type: 'string',
8271
8418
  description: 'Converted to user base currency (Decimal string)',
8272
8419
  example: '21600',
8273
8420
  nullable: true
@@ -8343,13 +8490,13 @@ export const $HoldingPnlRowDto = {
8343
8490
  example: 'Assets:US:Broker:AAPL'
8344
8491
  },
8345
8492
  accountCcy: {
8346
- type: 'object',
8493
+ type: 'string',
8347
8494
  description: 'Account settlement currency (ISO 4217), from cost currency',
8348
8495
  nullable: true,
8349
8496
  example: 'USD'
8350
8497
  },
8351
8498
  brokerType: {
8352
- type: 'object',
8499
+ type: 'string',
8353
8500
  description: 'Broker type derived from Platform.type',
8354
8501
  nullable: true,
8355
8502
  example: 'broker'
@@ -8370,7 +8517,7 @@ export const $HoldingPnlRowDto = {
8370
8517
  example: 'EQUITY'
8371
8518
  },
8372
8519
  assetSubClass: {
8373
- type: 'object',
8520
+ type: 'string',
8374
8521
  nullable: true,
8375
8522
  example: 'STOCK'
8376
8523
  },
@@ -8417,14 +8564,14 @@ export const $HoldingPnlRowDto = {
8417
8564
  ]
8418
8565
  },
8419
8566
  unrealizedPnlBase: {
8420
- type: 'object',
8567
+ type: 'string',
8421
8568
  description:
8422
8569
  'Unrealized P&L in base currency (Decimal string); null when any FX/price missing',
8423
8570
  nullable: true,
8424
8571
  example: '6000'
8425
8572
  },
8426
8573
  unrealizedPnlPct: {
8427
- type: 'object',
8574
+ type: 'string',
8428
8575
  description: 'Unrealized P&L % (Decimal string)',
8429
8576
  nullable: true,
8430
8577
  example: '25'
@@ -8448,7 +8595,7 @@ export const $HoldingPnlRowDto = {
8448
8595
  ]
8449
8596
  },
8450
8597
  pctOfInvestedAssets: {
8451
- type: 'object',
8598
+ type: 'string',
8452
8599
  description:
8453
8600
  'Share of invested assets % (Decimal string); only for invested chartTokens',
8454
8601
  nullable: true,
@@ -8493,15 +8640,15 @@ export const $HoldingPnlWarningDto = {
8493
8640
  ]
8494
8641
  },
8495
8642
  symbol: {
8496
- type: 'object',
8643
+ type: 'string',
8497
8644
  nullable: true
8498
8645
  },
8499
8646
  accountId: {
8500
- type: 'object',
8647
+ type: 'string',
8501
8648
  nullable: true
8502
8649
  },
8503
8650
  currency: {
8504
- type: 'object',
8651
+ type: 'string',
8505
8652
  nullable: true
8506
8653
  }
8507
8654
  },
@@ -8631,7 +8778,7 @@ export const $ParserContributionSamplesDto = {
8631
8778
  'Client-sanitized sample rows (key = column name, value = cell)',
8632
8779
  type: 'array',
8633
8780
  items: {
8634
- type: 'string'
8781
+ type: 'object'
8635
8782
  }
8636
8783
  },
8637
8784
  rawHeaders: {
@@ -8765,7 +8912,7 @@ export const $ParserContributionRelayResponseDto = {
8765
8912
  properties: {
8766
8913
  issueUrl: {
8767
8914
  type: 'string',
8768
- example: 'https://github.com/fire-la/parsers/issues/42'
8915
+ example: 'https://github.com/fire-zu/firela-vlt/issues/42'
8769
8916
  },
8770
8917
  issueNumber: {
8771
8918
  type: 'number',
@@ -8783,35 +8930,35 @@ export const $SymbolSearchResultDto = {
8783
8930
  example: 'AAPL'
8784
8931
  },
8785
8932
  name: {
8786
- type: 'object',
8933
+ type: 'string',
8787
8934
  example: 'Apple Inc.',
8788
8935
  nullable: true
8789
8936
  },
8790
8937
  exchange: {
8791
- type: 'object',
8938
+ type: 'string',
8792
8939
  example: 'US',
8793
8940
  nullable: true
8794
8941
  },
8795
8942
  assetType: {
8796
- type: 'object',
8943
+ type: 'string',
8797
8944
  description: 'OpenBB asset_type (e.g. stock, etf)',
8798
8945
  example: 'stock',
8799
8946
  nullable: true
8800
8947
  },
8801
8948
  assetClass: {
8802
- type: 'object',
8949
+ type: 'string',
8803
8950
  description: 'IGN asset class (region.types.ts ASSET_CLASSES)',
8804
8951
  example: 'EQUITY',
8805
8952
  nullable: true
8806
8953
  },
8807
8954
  assetSubClass: {
8808
- type: 'object',
8955
+ type: 'string',
8809
8956
  description: 'IGN asset sub-class (region.types.ts ASSET_SUB_CLASSES)',
8810
8957
  example: 'STOCK',
8811
8958
  nullable: true
8812
8959
  },
8813
8960
  currency: {
8814
- type: 'object',
8961
+ type: 'string',
8815
8962
  description: 'Trading currency (extra_data or inferred from exchange)',
8816
8963
  example: 'USD',
8817
8964
  nullable: true
@@ -8828,90 +8975,90 @@ export const $SymbolQuoteDto = {
8828
8975
  example: 'AAPL'
8829
8976
  },
8830
8977
  name: {
8831
- type: 'object',
8978
+ type: 'string',
8832
8979
  example: 'Apple Inc.',
8833
8980
  nullable: true
8834
8981
  },
8835
8982
  exchange: {
8836
- type: 'object',
8983
+ type: 'string',
8837
8984
  example: 'US',
8838
8985
  nullable: true
8839
8986
  },
8840
8987
  assetType: {
8841
- type: 'object',
8988
+ type: 'string',
8842
8989
  description: 'OpenBB asset_type',
8843
8990
  example: 'stock',
8844
8991
  nullable: true
8845
8992
  },
8846
8993
  assetClass: {
8847
- type: 'object',
8994
+ type: 'string',
8848
8995
  description: 'IGN asset class',
8849
8996
  example: 'EQUITY',
8850
8997
  nullable: true
8851
8998
  },
8852
8999
  assetSubClass: {
8853
- type: 'object',
9000
+ type: 'string',
8854
9001
  description: 'IGN asset sub-class',
8855
9002
  example: 'STOCK',
8856
9003
  nullable: true
8857
9004
  },
8858
9005
  currency: {
8859
- type: 'object',
9006
+ type: 'string',
8860
9007
  description: 'Trading currency (extra_data or inferred from exchange)',
8861
9008
  example: 'USD',
8862
9009
  nullable: true
8863
9010
  },
8864
9011
  price: {
8865
- type: 'object',
9012
+ type: 'string',
8866
9013
  description: 'Latest price (Decimal string)',
8867
9014
  example: '189.84',
8868
9015
  nullable: true
8869
9016
  },
8870
9017
  priceDate: {
8871
- type: 'object',
9018
+ type: 'string',
8872
9019
  description: 'Date the price was observed (ISO yyyy-MM-dd)',
8873
9020
  example: '2026-08-05',
8874
9021
  nullable: true
8875
9022
  },
8876
9023
  changePercent: {
8877
- type: 'object',
9024
+ type: 'number',
8878
9025
  description:
8879
9026
  '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.',
8880
9027
  example: 1.7,
8881
9028
  nullable: true
8882
9029
  },
8883
9030
  prevClose: {
8884
- type: 'object',
9031
+ type: 'string',
8885
9032
  description: 'Previous close (Decimal string)',
8886
9033
  nullable: true
8887
9034
  },
8888
9035
  open: {
8889
- type: 'object',
9036
+ type: 'string',
8890
9037
  description: 'Day open (Decimal string)',
8891
9038
  nullable: true
8892
9039
  },
8893
9040
  high: {
8894
- type: 'object',
9041
+ type: 'string',
8895
9042
  description: 'Day high (Decimal string)',
8896
9043
  nullable: true
8897
9044
  },
8898
9045
  low: {
8899
- type: 'object',
9046
+ type: 'string',
8900
9047
  description: 'Day low (Decimal string)',
8901
9048
  nullable: true
8902
9049
  },
8903
9050
  volume: {
8904
- type: 'object',
9051
+ type: 'string',
8905
9052
  description: 'Day volume (Decimal string)',
8906
9053
  nullable: true
8907
9054
  },
8908
9055
  yearHigh: {
8909
- type: 'object',
9056
+ type: 'string',
8910
9057
  description: '52-week high (Decimal string)',
8911
9058
  nullable: true
8912
9059
  },
8913
9060
  yearLow: {
8914
- type: 'object',
9061
+ type: 'string',
8915
9062
  description: '52-week low (Decimal string)',
8916
9063
  nullable: true
8917
9064
  }