@dossier-wiki/os-sdk 0.1.0 → 0.7.0

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.
package/dist/types.d.ts CHANGED
@@ -2,6 +2,124 @@ export interface Paginated<T> {
2
2
  data: T[];
3
3
  pagination: PaginationMeta;
4
4
  }
5
+ /** A resource tag assignment: slugified `value` + snapshotted `label`. */
6
+ export interface TagValue {
7
+ /** Slugified, stable key (catalogue value). */
8
+ value: string;
9
+ /** Human-readable label snapshot at assignment time. */
10
+ label: string;
11
+ }
12
+ /**
13
+ * Tag assignment input. Pass `label` only and the slug `value` is derived
14
+ * server-side, or pass both to pin a specific catalogue value.
15
+ */
16
+ export interface TagValueInput {
17
+ label: string;
18
+ value?: string;
19
+ }
20
+ /** The eight catalogue-governed tag field-keys. */
21
+ export type TagFieldKey = 'customer.tags' | 'customer.riskTags' | 'counterparty.tags' | 'counterparty.riskTags' | 'alert.dispositionTags' | 'address.tags' | 'rule.tags' | 'identificationDocument.tags';
22
+ export type TagCatalogueEnforcement = 'open' | 'strict';
23
+ export interface TagCatalogueEntry {
24
+ id: string;
25
+ fieldKey: TagFieldKey;
26
+ value: string;
27
+ label: string;
28
+ color?: string | null;
29
+ description?: string | null;
30
+ archivedAt?: string | null;
31
+ createdAt: string;
32
+ updatedAt: string;
33
+ }
34
+ export interface TagCatalogueEntryInput {
35
+ fieldKey: TagFieldKey;
36
+ label: string;
37
+ value?: string;
38
+ color?: string;
39
+ description?: string;
40
+ }
41
+ export interface UpdateTagCatalogueEntryInput {
42
+ label?: string;
43
+ color?: string;
44
+ description?: string;
45
+ }
46
+ export interface TagFieldEnforcement {
47
+ fieldKey: TagFieldKey;
48
+ enforcement: TagCatalogueEnforcement;
49
+ }
50
+ export interface SetTagEnforcementInput {
51
+ fieldKey: TagFieldKey;
52
+ enforcement: TagCatalogueEnforcement;
53
+ }
54
+ export type TypedFieldType = 'TEXT' | 'NUMBER' | 'BOOLEAN' | 'DATE' | 'SET' | 'CURRENCY' | 'MONETARY';
55
+ /** Schema declaration carried on a parent resource (e.g. `Product.typedAccountFieldConfig`). */
56
+ export interface TypedFieldDefinition {
57
+ key: string;
58
+ displayName: string;
59
+ type: TypedFieldType;
60
+ required: boolean;
61
+ /** Default applied at write time when the caller omits the key. Raw value, validated against `type`. */
62
+ defaultValue?: unknown;
63
+ description?: string | null;
64
+ }
65
+ /**
66
+ * Caller-facing input for one typed key/value entry. `type` tells the
67
+ * backend validator how to interpret `value`:
68
+ * - TEXT / DATE / CURRENCY → string
69
+ * - NUMBER → finite JS number
70
+ * - BOOLEAN → boolean
71
+ * - SET → string[]
72
+ * - MONETARY → denominated literal `"<amount>@<TYPE:CODE>"`, e.g. `"50000.00@FIAT:USD"`
73
+ */
74
+ export interface TypedFieldValueInput {
75
+ key: string;
76
+ type: TypedFieldType;
77
+ value: unknown;
78
+ }
79
+ /** Untyped escape-hatch input (Tier C). Stored verbatim. */
80
+ export interface UntypedKeyValueInput {
81
+ key: string;
82
+ value: unknown;
83
+ }
84
+ /**
85
+ * Read shape for one typed key/value entry. Wire-format `type` strings use
86
+ * the lowercase form. Monetary carries pre-resolved minor units.
87
+ */
88
+ export type TypedFieldStored = {
89
+ key: string;
90
+ type: 'text';
91
+ value: string;
92
+ } | {
93
+ key: string;
94
+ type: 'number';
95
+ value: number;
96
+ } | {
97
+ key: string;
98
+ type: 'boolean';
99
+ value: boolean;
100
+ } | {
101
+ key: string;
102
+ type: 'date';
103
+ value: string;
104
+ } | {
105
+ key: string;
106
+ type: 'set';
107
+ value: string[];
108
+ } | {
109
+ key: string;
110
+ type: 'currency';
111
+ value: string;
112
+ } | {
113
+ key: string;
114
+ type: 'monetary';
115
+ amountMinor: number;
116
+ currency: string;
117
+ precision: number;
118
+ };
119
+ export interface UntypedKeyValueDto {
120
+ key: string;
121
+ value: unknown;
122
+ }
5
123
  export interface AccountResponseDto {
6
124
  id: string;
7
125
  externalId?: string;
@@ -12,11 +130,10 @@ export interface AccountResponseDto {
12
130
  accountType: 'CHECKING' | 'SAVINGS' | 'OPERATING' | 'TRUST' | 'INVESTMENT' | 'ESCROW' | 'CREDIT_CARD' | 'LINE_OF_CREDIT' | 'PERSONAL_LOAN' | 'MORTGAGE' | 'AUTO_LOAN' | 'BUSINESS_LOAN' | 'CRYPTO_WALLET' | 'MOBILE_WALLET' | 'PREPAID_CARD' | 'E_WALLET' | 'BROKERAGE' | 'FUND' | 'OTHER';
13
131
  status: 'ACTIVE' | 'FROZEN' | 'CLOSED' | 'DORMANT';
14
132
  currency?: string;
15
- bankName?: string;
16
- bankSwift?: string;
17
- iban?: string;
18
- accountNumber?: string;
19
- customProperties?: Record<string, unknown>;
133
+ /** Typed Field bag (Tier A). Validated against `Product.typedAccountFieldConfig`. */
134
+ fields?: TypedFieldStored[];
135
+ /** Untyped escape hatch (Tier C). */
136
+ otherProperties?: UntypedKeyValueDto[];
20
137
  openedAt: string;
21
138
  closedAt?: string;
22
139
  }
@@ -35,14 +152,110 @@ export interface AddIdentificationDocumentDto {
35
152
  notes?: string;
36
153
  attachments?: AttachmentDto[];
37
154
  }
155
+ export type AddressCategory = 'HOME' | 'MAILING' | 'BILLING' | 'WORK' | 'REGISTERED' | 'HEADQUARTERS' | 'BRANCH' | 'OFFICE' | 'WAREHOUSE' | 'STORE' | 'OTHER';
156
+ export type Iso20022AddressType = 'BIZZ' | 'DLVY' | 'HOME' | 'MLTO' | 'PBOX' | 'ADDR';
157
+ export type AddressVerificationStatus = 'PENDING' | 'VERIFIED' | 'REJECTED' | 'EXPIRED';
158
+ export type Lifecycle = 'LIVE' | 'ARCHIVED' | 'TOMBSTONED';
159
+ export interface AddressCoordinatesDto {
160
+ lat?: number;
161
+ lng?: number;
162
+ /** Provenance, e.g. 'manual', 'google.geocode'. */
163
+ source?: string;
164
+ /** ISO 8601 timestamp. */
165
+ resolvedAt?: string;
166
+ }
167
+ /**
168
+ * Operational postal address. Lives in the polymorphic `addresses` table on the
169
+ * server (owner = CUSTOMER / COUNTERPARTY / INSTITUTION). Exposed on the Customer
170
+ * subtypes as `Individual.addresses` and `Entity.locations` — same shape, different
171
+ * semantic field name.
172
+ *
173
+ * Categories (semantic) and `iso20022Type` (wire-protocol) are parallel
174
+ * discriminators; customer rows use `category`, counterparty/institution rows
175
+ * carry `iso20022Type` when transcribed off CBPR+ payloads.
176
+ *
177
+ * Distinct from `IdDocAddressDto` below, which is the snapshot address
178
+ * transcribed from an identification document image — that one stays as jsonb
179
+ * on the identification_documents row and never reaches the addresses table.
180
+ */
38
181
  export interface AddressDto {
39
- line1: string;
182
+ id: string;
183
+ ownerResourceType: 'CUSTOMER' | 'COUNTERPARTY' | 'INSTITUTION';
184
+ ownerResourceId: string;
185
+ category?: AddressCategory | null;
186
+ iso20022Type?: Iso20022AddressType | null;
187
+ tags: TagValue[];
188
+ note?: string | null;
189
+ line1?: string | null;
190
+ line2?: string | null;
191
+ city?: string | null;
192
+ state?: string | null;
193
+ postalCode?: string | null;
194
+ /** ISO 3166-1 alpha-3 country code. Required. */
195
+ country: string;
196
+ /** ISO 20022 PostalAddress27 overflow fields (department, buildingNumber, …). */
197
+ iso20022Details?: Record<string, unknown> | null;
198
+ /** YYYY-MM-DD */
199
+ validFrom?: string | null;
200
+ /** YYYY-MM-DD */
201
+ validTo?: string | null;
202
+ coordinates?: AddressCoordinatesDto | null;
203
+ /** Free-form location URL — Google Maps, OpenStreetMap, what3words, etc. */
204
+ locationLink?: string | null;
205
+ verificationStatus: AddressVerificationStatus;
206
+ verifiedAt?: string | null;
207
+ verifiedBy?: {
208
+ id: string;
209
+ name?: string;
210
+ } | null;
211
+ expiresAt?: string | null;
212
+ rejectionReason?: string | null;
213
+ documentIds: string[];
214
+ lifecycle: Lifecycle;
215
+ createdAt: string;
216
+ updatedAt: string;
217
+ }
218
+ /**
219
+ * Inline shape for fan-out from create paths and as the body of `addAddress`.
220
+ * Owner is supplied by the caller (parent customer for inline-on-create, or
221
+ * explicitly on the granular endpoint).
222
+ */
223
+ export interface AddressInputDto {
224
+ category?: AddressCategory;
225
+ iso20022Type?: Iso20022AddressType;
226
+ tags?: TagValueInput[];
227
+ note?: string;
228
+ line1?: string;
40
229
  line2?: string;
41
- city: string;
230
+ city?: string;
42
231
  state?: string;
43
- postalCode: string;
44
- /** ISO 3166-1 alpha-3 country code */
232
+ postalCode?: string;
233
+ /** ISO 3166-1 alpha-3 country code. Required. */
45
234
  country: string;
235
+ iso20022Details?: Record<string, unknown>;
236
+ /** YYYY-MM-DD */
237
+ validFrom?: string;
238
+ /** YYYY-MM-DD */
239
+ validTo?: string;
240
+ coordinates?: AddressCoordinatesDto;
241
+ /** Free-form location URL — Google Maps, OpenStreetMap, what3words, etc. */
242
+ locationLink?: string;
243
+ documentIds?: string[];
244
+ }
245
+ /**
246
+ * Snapshot of an address transcribed from an identification document
247
+ * (passport, ID card, …). Stays as jsonb on the document row; never reaches
248
+ * the polymorphic addresses table.
249
+ */
250
+ export interface IdDocAddressDto {
251
+ tag?: string;
252
+ line1?: string;
253
+ line2?: string;
254
+ city?: string;
255
+ state?: string;
256
+ postalCode?: string;
257
+ /** ISO 3166-1 alpha-3 country code */
258
+ country?: string;
46
259
  }
47
260
  export interface AlternateNameDto {
48
261
  name: string;
@@ -206,7 +419,8 @@ export interface CounterpartyResponseDto {
206
419
  identity: 'INDIVIDUAL' | 'ENTITY' | 'UNKNOWN';
207
420
  classification: 'BANK_ACCOUNT' | 'WALLET' | 'MERCHANT' | 'FINANCIAL_INSTITUTION' | 'PAYMENT_NETWORK' | 'UNKNOWN';
208
421
  country?: string;
209
- riskLevel: 'HIGH' | 'MEDIUM' | 'LOW' | 'UNRATED';
422
+ /** Unified risk rating; null = unrated (was `riskLevel` with UNRATED). */
423
+ riskRating: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL' | null;
210
424
  source: 'MANUAL' | 'SYSTEM';
211
425
  linkedCustomerIds: string[];
212
426
  /** ID of the transaction that first created this counterparty */
@@ -217,25 +431,34 @@ export interface CounterpartyResponseDto {
217
431
  institution?: InstitutionDetailsDto;
218
432
  firstTransactionAt?: string;
219
433
  lastTransactionAt?: string;
434
+ /** Untyped escape hatch (Tier C). */
435
+ otherProperties?: UntypedKeyValueDto[];
220
436
  createdAt: string;
221
437
  updatedAt: string;
222
438
  }
223
439
  export interface CreateAccountDto {
224
- /** Your external identifier */
440
+ /**
441
+ * Customer to register as the PRIMARY owner. Written into
442
+ * `account_owners`, not stored on the accounts row (D18).
443
+ */
444
+ primaryCustomerId: string;
445
+ /** Your external identifier. Defaults to `ACC-${timestamp}`. */
225
446
  externalId?: string;
226
- /** Product ID this account is based on */
447
+ /**
448
+ * Product this account is instantiated from. Determines `accountCategory`
449
+ * / `accountType` and the required typed-field schema — those are NOT
450
+ * accepted from the caller (Phase 3b).
451
+ */
227
452
  productId?: string;
228
453
  label: string;
229
- accountCategory: 'DEPOSIT' | 'CREDIT' | 'LOAN' | 'WALLET' | 'SECURITIES' | 'OTHER';
230
- accountType: 'CHECKING' | 'SAVINGS' | 'OPERATING' | 'TRUST' | 'INVESTMENT' | 'ESCROW' | 'CREDIT_CARD' | 'LINE_OF_CREDIT' | 'PERSONAL_LOAN' | 'MORTGAGE' | 'AUTO_LOAN' | 'BUSINESS_LOAN' | 'CRYPTO_WALLET' | 'MOBILE_WALLET' | 'PREPAID_CARD' | 'E_WALLET' | 'BROKERAGE' | 'FUND' | 'OTHER';
231
- /** Currency code (ISO 4217) */
454
+ /** Currency code (ISO 4217 / `TYPE:CODE`). Falls back to `product.defaultCurrency`. */
232
455
  currency?: string;
233
- bankName?: string;
234
- bankSwift?: string;
235
- iban?: string;
236
- accountNumber?: string;
237
- /** Arbitrary key-value properties */
238
- customProperties?: Record<string, unknown>;
456
+ /** Typed Field write input (Tier A). Validated against `Product.typedAccountFieldConfig`. */
457
+ fields?: TypedFieldValueInput[];
458
+ /** Untyped escape hatch (Tier C). Stored verbatim. */
459
+ otherProperties?: UntypedKeyValueInput[];
460
+ /** Customer IDs to add as JOINT owners alongside the primary. */
461
+ additionalOwnerIds?: string[];
239
462
  /** Override account opening timestamp (ISO 8601). Used by data-loading tools to backfill historical accounts. */
240
463
  openedAt?: string;
241
464
  }
@@ -255,7 +478,7 @@ export interface CreateConstantDto {
255
478
  /** Scope (derived from name if omitted). */
256
479
  scope?: 'global' | 'product' | 'customer' | 'account' | 'counterparty' | 'instrument' | 'device';
257
480
  /** Constant type. Determines the required shape of `value`. */
258
- type: 'scalar' | 'monetary' | 'set' | 'range' | 'text' | 'number' | 'boolean' | 'date' | 'currency';
481
+ type: 'scalar' | 'monetary' | 'set' | 'range' | 'text' | 'number' | 'boolean' | 'date' | 'currency' | 'regex';
259
482
  /** Payload shape depends on the constant's `type`. Pick the matching variant below. Validated at write time. */
260
483
  value: {
261
484
  /** e.g. `"1000000@FIAT:USD"` = $10,000.00. Precision implied by currency: USD=2, JPY=0, BTC=8, ETH=9, USDT/USDC=6. */
@@ -302,7 +525,10 @@ export interface CreateEntityDto {
302
525
  parentEntityId?: string;
303
526
  email?: string;
304
527
  phone?: string;
305
- addresses?: AddressDto[];
528
+ /** Inline fan-out into the polymorphic `addresses` table. Same shape as
529
+ * Individual.addresses; field is named `locations` to match the read-side
530
+ * GraphQL field for entities. */
531
+ locations?: AddressInputDto[];
306
532
  /** Override creation timestamp (ISO 8601). Used by data-loading tools to backfill historical entities. */
307
533
  createdAt?: string;
308
534
  }
@@ -333,7 +559,8 @@ export interface CreateIndividualDto {
333
559
  email?: string;
334
560
  phone?: string;
335
561
  identificationDocuments?: IdentificationDocumentDto[];
336
- addresses?: AddressDto[];
562
+ /** Inline fan-out into the polymorphic `addresses` table. */
563
+ addresses?: AddressInputDto[];
337
564
  /** Override creation timestamp (ISO 8601). Used by data-loading tools to backfill historical customers. */
338
565
  createdAt?: string;
339
566
  }
@@ -358,22 +585,29 @@ export interface CreateProductDto {
358
585
  country?: string;
359
586
  /** Supported transaction method IDs. */
360
587
  supportedMethodIds: string[];
361
- /** Arbitrary product metadata. */
362
- metadata?: Record<string, unknown>;
588
+ /**
589
+ * Typed Field schema for accounts of this product (Tier A). Each entry is
590
+ * a `TypedFieldDefinition`; validates `Account.fields` writes.
591
+ */
592
+ typedAccountFieldConfig?: TypedFieldDefinition[];
593
+ /** Product-level typed bag (Tier B, self-declaring). */
594
+ fields?: TypedFieldValueInput[];
595
+ /** Untyped escape hatch (Tier C). */
596
+ otherProperties?: UntypedKeyValueInput[];
363
597
  /** Sync key for config-as-code management. */
364
598
  syncKey?: string;
365
599
  }
366
600
  export interface CreateRiskAssessmentDto {
367
601
  answers: RiskAssessmentAnswerDto[];
368
- resultingRiskLevel: 'HIGH' | 'MEDIUM' | 'LOW' | 'UNRATED';
369
- computedRiskLevel?: 'HIGH' | 'MEDIUM' | 'LOW' | 'UNRATED';
602
+ resultingRiskRating: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
603
+ computedRiskRating?: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
370
604
  ratingOverridden?: boolean;
371
605
  overrideJustification?: string;
372
606
  narrative?: string;
373
- riskTags?: string[];
607
+ riskTags?: TagValueInput[];
374
608
  }
375
- export interface CreateRiskQuestionnaireDto {
376
- answers: RiskQuestionnaireAnswerDto[];
609
+ export interface CreateCustomerRiskAssessmentDto {
610
+ answers: CustomerRiskAssessmentAnswerDto[];
377
611
  /** Optional narrative summary */
378
612
  narrative?: string;
379
613
  }
@@ -388,8 +622,8 @@ export interface CreateRuleDto {
388
622
  trigger?: string;
389
623
  /** Rule severity. */
390
624
  severity: 'HIGH' | 'MEDIUM' | 'LOW';
391
- /** Tags for categorisation. */
392
- tags?: string[];
625
+ /** Tags for categorisation (tag catalogue). */
626
+ tags?: TagValueInput[];
393
627
  /** Condition tree (AND/OR logic with leaf conditions). */
394
628
  conditionTree?: Record<string, unknown>;
395
629
  /** Actions to execute when the rule triggers. */
@@ -504,7 +738,9 @@ export interface EntityResponseDto {
504
738
  riskRating: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
505
739
  kycTier?: 'NO_KYC' | 'SDD' | 'CDD' | 'EDD' | 'ONGOING';
506
740
  alertCount: number;
507
- addresses: AddressDto[];
741
+ /** Operational footprint (REGISTERED office, BRANCH, WAREHOUSE, …). Read-only here;
742
+ * use granular add/update/remove/verify/reject mutations on the addresses endpoint. */
743
+ locations: AddressDto[];
508
744
  createdAt: string;
509
745
  updatedAt: string;
510
746
  }
@@ -562,8 +798,12 @@ export interface UserRef {
562
798
  email?: string;
563
799
  role?: string;
564
800
  avatar?: string;
565
- /** Discriminates human users from service principals. */
566
- type?: 'USER' | 'SERVICE';
801
+ /**
802
+ * Discriminates actor variants. `UNRESOLVED` marks rows whose original
803
+ * actor predates the platform-wide actor standardization and could not
804
+ * be classified during the backfill.
805
+ */
806
+ type?: 'USER' | 'SERVICE' | 'UNRESOLVED';
567
807
  apiKeySanitized?: string;
568
808
  }
569
809
  export interface RichAddressDto {
@@ -636,7 +876,7 @@ export interface IdentificationDocument {
636
876
  status: IdentificationDocumentStatus;
637
877
  effectiveStatus: IdentificationDocumentEffectiveStatus;
638
878
  rejectionNarrative?: string;
639
- tags: string[];
879
+ tags: TagValue[];
640
880
  attachments: IdDocFileAttachment[];
641
881
  /** @deprecated Use attachments[].fileId instead. */
642
882
  fileIds?: string[];
@@ -669,7 +909,7 @@ export interface CreateIdentificationDocumentInput {
669
909
  sex?: string;
670
910
  /** Free-form key/value metadata. */
671
911
  other?: Record<string, unknown>;
672
- tags?: string[];
912
+ tags?: TagValueInput[];
673
913
  attachments?: IdDocFileAttachmentInput[];
674
914
  notes?: string;
675
915
  }
@@ -685,7 +925,7 @@ export interface UpdateIdentificationDocumentInput {
685
925
  dateOfBirth?: string;
686
926
  sex?: string;
687
927
  other?: Record<string, unknown>;
688
- tags?: string[];
928
+ tags?: TagValueInput[];
689
929
  attachments?: IdDocFileAttachmentInput[];
690
930
  notes?: string;
691
931
  }
@@ -804,6 +1044,8 @@ export interface IndividualResponseDto {
804
1044
  kycTier?: 'NO_KYC' | 'SDD' | 'CDD' | 'EDD' | 'ONGOING';
805
1045
  alertCount: number;
806
1046
  identificationDocuments: IdentificationDocumentDto[];
1047
+ /** Postal addresses (HOME / MAILING / BILLING / WORK). Read-only here;
1048
+ * use granular add/update/remove/verify/reject mutations on the addresses endpoint. */
807
1049
  addresses: AddressDto[];
808
1050
  createdAt: string;
809
1051
  updatedAt: string;
@@ -838,8 +1080,11 @@ export interface IngestEventDto {
838
1080
  deviceId?: string;
839
1081
  /** Session identifier for session-context rules. */
840
1082
  sessionId?: string;
841
- /** Event-specific payload data. Schema depends on event type. */
842
- data?: Record<string, unknown>;
1083
+ /**
1084
+ * Typed payload (Typed Fields primitive, Tier B). Validated via the
1085
+ * canonical TypedFields validator and stored in `events.fields`.
1086
+ */
1087
+ fields?: TypedFieldValueInput[];
843
1088
  }
844
1089
  export interface IngestTransactionDto {
845
1090
  /** Your unique identifier for this transaction. Used for idempotency. */
@@ -1145,7 +1390,7 @@ export interface RiskAssessmentAnswerDto {
1145
1390
  selectedOptionId?: string;
1146
1391
  notes?: string;
1147
1392
  }
1148
- export interface RiskQuestionnaireAnswerDto {
1393
+ export interface CustomerRiskAssessmentAnswerDto {
1149
1394
  questionId: string;
1150
1395
  question: string;
1151
1396
  answer: string;
@@ -1194,23 +1439,22 @@ export interface TransactionBodyDto {
1194
1439
  metadata?: Record<string, string | number | boolean | MetadataTextWrapperDto | MetadataNumberWrapperDto | MetadataBooleanWrapperDto | MetadataDateWrapperDto | MetadataSetWrapperDto | MetadataCurrencyWrapperDto | MetadataMonetaryWrapperDto>;
1195
1440
  }
1196
1441
  export interface UpdateAccountDto {
1197
- /** Product ID this account is based on */
1198
- productId?: string;
1199
1442
  label?: string;
1200
- /** Currency code (ISO 4217) */
1201
- currency?: string;
1202
- bankName?: string;
1203
- bankSwift?: string;
1204
- iban?: string;
1205
- accountNumber?: string;
1206
- /** Arbitrary key-value properties */
1207
- customProperties?: Record<string, unknown>;
1208
1443
  /** Override account opening timestamp (ISO 8601). Used by data-loading tools to backfill historical accounts. */
1209
1444
  openedAt?: string;
1445
+ /**
1446
+ * Typed Field write input (Tier A). Merge semantics — supplied keys
1447
+ * overwrite the stored bag, absent keys are preserved. Pass `[]` to clear.
1448
+ * Banking-style values (IBAN, SWIFT, account number, …) live here now,
1449
+ * not as flat columns (Phase 3b).
1450
+ */
1451
+ fields?: TypedFieldValueInput[];
1452
+ /** Untyped escape hatch (Tier C). Stored verbatim. */
1453
+ otherProperties?: UntypedKeyValueInput[];
1210
1454
  }
1211
1455
  export interface UpdateConstantDto {
1212
1456
  /** Constant type. If changed, `value` must be re-supplied in the new shape. */
1213
- type?: 'scalar' | 'monetary' | 'set' | 'range' | 'text' | 'number' | 'boolean' | 'date' | 'currency';
1457
+ type?: 'scalar' | 'monetary' | 'set' | 'range' | 'text' | 'number' | 'boolean' | 'date' | 'currency' | 'regex';
1214
1458
  /** Payload shape depends on the constant's `type`. Pick the matching variant below. Validated at write time. */
1215
1459
  value?: {
1216
1460
  /** e.g. `"1000000@FIAT:USD"` = $10,000.00. Precision implied by currency: USD=2, JPY=0, BTC=8, ETH=9, USDT/USDC=6. */
@@ -1255,7 +1499,6 @@ export interface UpdateEntityDto {
1255
1499
  parentEntityId?: string;
1256
1500
  email?: string;
1257
1501
  phone?: string;
1258
- addresses?: AddressDto[];
1259
1502
  /**
1260
1503
  * Generic key/value entries to upsert onto the entity record. Merge semantics —
1261
1504
  * unlisted keys are left untouched.
@@ -1313,7 +1556,6 @@ export interface UpdateIndividualDto {
1313
1556
  email?: string;
1314
1557
  phone?: string;
1315
1558
  identificationDocuments?: IdentificationDocumentDto[];
1316
- addresses?: AddressDto[];
1317
1559
  /**
1318
1560
  * Generic key/value entries to upsert onto the customer record. Merge semantics —
1319
1561
  * unlisted keys are left untouched. Use this for fields without first-class columns
@@ -1377,14 +1619,32 @@ export interface UpdateProductDto {
1377
1619
  status?: string;
1378
1620
  /** Supported transaction method IDs. */
1379
1621
  supportedMethodIds?: string[];
1380
- /** Arbitrary product metadata. */
1381
- metadata?: Record<string, unknown>;
1622
+ /** Typed Field schema for accounts of this product (Tier A). */
1623
+ typedAccountFieldConfig?: TypedFieldDefinition[];
1624
+ /** Product-level typed bag (Tier B, self-declaring). */
1625
+ fields?: TypedFieldValueInput[];
1626
+ /** Untyped escape hatch (Tier C). */
1627
+ otherProperties?: UntypedKeyValueInput[];
1382
1628
  }
1383
1629
  export interface UpdateRiskRatingDto {
1384
1630
  riskRating: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
1385
1631
  /** Justification for the override */
1386
1632
  justification?: string;
1387
1633
  }
1634
+ /** Lifecycle status of a customer (individual or entity). */
1635
+ export type CustomerStatus = 'ONBOARDING' | 'IN_REVIEW' | 'ACTIVE' | 'INACTIVE' | 'SUSPENDED' | 'REJECTED';
1636
+ export interface UpdateCustomerStatusDto {
1637
+ /** New lifecycle status for the customer. */
1638
+ status: CustomerStatus;
1639
+ /** Audit reason for the status change. */
1640
+ reason?: string;
1641
+ }
1642
+ export interface UpdateCustomerStatusResponse {
1643
+ customerId: string;
1644
+ status: CustomerStatus;
1645
+ statusReason: string | null;
1646
+ updatedAt: string;
1647
+ }
1388
1648
  export interface UpdateRuleDto {
1389
1649
  /** Rule name. */
1390
1650
  name?: string;
@@ -1396,8 +1656,8 @@ export interface UpdateRuleDto {
1396
1656
  trigger?: string;
1397
1657
  /** Rule severity. */
1398
1658
  severity?: 'HIGH' | 'MEDIUM' | 'LOW';
1399
- /** Tags for categorisation. */
1400
- tags?: string[];
1659
+ /** Tags for categorisation (tag catalogue). */
1660
+ tags?: TagValueInput[];
1401
1661
  /** Rule status. */
1402
1662
  status?: 'DRAFT' | 'ACTIVE' | 'DISABLED';
1403
1663
  /** Condition tree. */
@@ -1493,6 +1753,11 @@ export interface GetCustomerQuery {
1493
1753
  /** If true, treat the path id as an external customer ID. */
1494
1754
  isExternal?: boolean;
1495
1755
  }
1756
+ /**
1757
+ * Response DTOs not enumerated in the public OpenAPI schema. The backend
1758
+ * returns these as full objects but the OpenAPI spec does not publish their
1759
+ * shape. Treated as opaque records — narrow on the caller side.
1760
+ */
1496
1761
  export type OpaqueResponse = Record<string, unknown>;
1497
1762
  export type ApiKeyResponseDto = OpaqueResponse;
1498
1763
  export type TokenResponseDto = OpaqueResponse;
@@ -1536,7 +1801,7 @@ export type PlatformConfirmUploadResponseDto = OpaqueResponse;
1536
1801
  export type StakeholderResponseDto = OpaqueResponse;
1537
1802
  export type DeviceResponseDto = OpaqueResponse;
1538
1803
  export type DeviceSummaryDto = OpaqueResponse;
1539
- export type RiskQuestionnaireResponseDto = OpaqueResponse;
1804
+ export type CustomerRiskAssessmentResponseDto = OpaqueResponse;
1540
1805
  export type RiskAssessmentResponseDto = OpaqueResponse;
1541
1806
  export type ExpectedActivityResponseDto = OpaqueResponse;
1542
1807
  export type ScreeningResultDto = OpaqueResponse;
@@ -1547,7 +1812,160 @@ export type ProductResponseDto = OpaqueResponse;
1547
1812
  export type CurrencyResponseDto = OpaqueResponse;
1548
1813
  export type EventDefinitionResponseDto = OpaqueResponse;
1549
1814
  export type WebhookResponseDto = OpaqueResponse;
1550
- export type SyncExportDto = OpaqueResponse;
1815
+ export interface SyncSnapshotActor {
1816
+ userId: string;
1817
+ name: string;
1818
+ }
1819
+ export interface SyncSnapshotDto {
1820
+ id: string;
1821
+ revision: number;
1822
+ contentHash: string;
1823
+ note: string | null;
1824
+ createdAt: string;
1825
+ createdBy: SyncSnapshotActor;
1826
+ /** Size of the gzipped JSON blob, in bytes. */
1827
+ byteSize: number;
1828
+ }
1829
+ export interface SyncDriftDto {
1830
+ hasDrift: boolean;
1831
+ latestRevision: number | null;
1832
+ latestSnapshotAt: string | null;
1833
+ changedRowCount: number;
1834
+ }
1835
+ export interface CreateSyncSnapshotInput {
1836
+ note?: string;
1837
+ }
1838
+ export interface SyncConfig {
1839
+ $schema?: string;
1840
+ version: number;
1841
+ tenant: {
1842
+ organizationId: string;
1843
+ baseCurrency?: string;
1844
+ displayName?: string;
1845
+ };
1846
+ productDefinitions?: Record<string, SyncProductDefinitionConfig | string>;
1847
+ constants?: Record<string, SyncConstantConfig>;
1848
+ eventDefinitions?: Record<string, SyncEventDefConfig>;
1849
+ webhooks?: Record<string, SyncWebhookConfig>;
1850
+ rules?: Record<string, SyncRuleConfig>;
1851
+ /** Keyed by TYPE:CODE (e.g. "FIAT:USD", "CRYPTO:BTC"). */
1852
+ currencies?: Record<string, SyncCurrencyConfig>;
1853
+ customerFieldPolicy?: Record<string, SyncCustomerFieldPolicyConfig>;
1854
+ accountStatusPolicy?: SyncAccountStatusPolicyConfig;
1855
+ }
1856
+ export interface SyncCurrencyConfig {
1857
+ name: string;
1858
+ symbol?: string;
1859
+ precision: number;
1860
+ enabled?: boolean;
1861
+ custom?: boolean;
1862
+ }
1863
+ export interface SyncConstantConfig {
1864
+ type: 'scalar' | 'monetary' | 'set' | 'range' | 'text' | 'number' | 'boolean' | 'date' | 'currency' | 'regex';
1865
+ description: string;
1866
+ values?: string[];
1867
+ value?: string | number | boolean | null;
1868
+ min?: number;
1869
+ max?: number;
1870
+ }
1871
+ export interface SyncProductDefinitionConfig {
1872
+ name: string;
1873
+ description?: string;
1874
+ category: string;
1875
+ baseType: string;
1876
+ defaultCurrency: string;
1877
+ country?: string;
1878
+ supportedMethods: string[];
1879
+ metadata?: Record<string, unknown>;
1880
+ }
1881
+ export interface SyncEventDefConfig {
1882
+ name: string;
1883
+ description: string;
1884
+ subject: 'CUSTOMER' | 'ACCOUNT' | 'TRANSACTION';
1885
+ }
1886
+ export interface SyncWebhookConfig {
1887
+ description: string;
1888
+ url: string;
1889
+ headers?: Record<string, string>;
1890
+ events: string[];
1891
+ }
1892
+ export interface SyncRuleConfig {
1893
+ name: string;
1894
+ description: string;
1895
+ subject: string;
1896
+ trigger: string;
1897
+ severity: 'HIGH' | 'MEDIUM' | 'LOW';
1898
+ tags?: string[];
1899
+ conditionTree: unknown;
1900
+ actions?: Array<Record<string, unknown>>;
1901
+ initialStatus?: 'DRAFT' | 'ACTIVE' | 'DISABLED';
1902
+ status?: 'DRAFT' | 'ACTIVE' | 'DISABLED';
1903
+ }
1904
+ export interface SyncCustomerFieldPolicyConfig {
1905
+ source: string;
1906
+ syncTrigger: string;
1907
+ usedBy: string[];
1908
+ }
1909
+ export interface SyncAccountStatusPolicyConfig {
1910
+ statuses: string[];
1911
+ dormancyThresholdDays?: number;
1912
+ dormancyStrategy?: 'MANUAL' | 'AUTO';
1913
+ usedBy?: Record<string, string[]>;
1914
+ }
1915
+ /** Request body for `validate` / `plan` / `apply`. */
1916
+ export interface SyncConfigBody {
1917
+ config: SyncConfig;
1918
+ }
1919
+ export type SyncDiffOpType = 'create' | 'update' | 'destroy' | 'archive' | 'tombstone';
1920
+ export interface SyncDiffOp {
1921
+ type: SyncDiffOpType;
1922
+ key: string;
1923
+ config?: unknown;
1924
+ changes?: string[];
1925
+ }
1926
+ export interface SyncImmutableViolation {
1927
+ section: string;
1928
+ key: string;
1929
+ field: string;
1930
+ liveValue: unknown;
1931
+ configValue: unknown;
1932
+ }
1933
+ export interface SyncPlan {
1934
+ products: SyncDiffOp[];
1935
+ constants: SyncDiffOp[];
1936
+ eventDefs: SyncDiffOp[];
1937
+ webhooks: SyncDiffOp[];
1938
+ rules: SyncDiffOp[];
1939
+ currencies: SyncDiffOp[];
1940
+ immutableViolations: SyncImmutableViolation[];
1941
+ }
1942
+ /** `POST /v1/config/sync/validate` response. */
1943
+ export interface SyncValidationResult {
1944
+ errors: string[];
1945
+ warnings: string[];
1946
+ }
1947
+ /** `POST /v1/config/sync/plan` response (validation + advisory diff). */
1948
+ export interface SyncPlanResult extends SyncValidationResult {
1949
+ plan: SyncPlan;
1950
+ }
1951
+ export interface SyncApplyResultItem {
1952
+ section: string;
1953
+ key: string;
1954
+ type: SyncDiffOpType;
1955
+ status: 'applied' | 'failed';
1956
+ error?: string;
1957
+ }
1958
+ /** `POST /v1/config/sync/apply` response. */
1959
+ export interface SyncApplyResult {
1960
+ succeeded: number;
1961
+ failed: number;
1962
+ results: SyncApplyResultItem[];
1963
+ immutableViolations: SyncImmutableViolation[];
1964
+ }
1965
+ export interface SyncExportQuery {
1966
+ /** Include rows without a sync key (keyed by natural id). Used by import/pull. */
1967
+ includeUnsynced?: boolean;
1968
+ }
1551
1969
  export type ResetConfigResponseDto = OpaqueResponse;
1552
1970
  export type PushExchangeRatesResponseDto = OpaqueResponse;
1553
1971
  export type BulkCurrencyStatusResponseDto = OpaqueResponse;