@robosystems/client 0.3.19 → 0.3.21

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.
@@ -67,6 +67,7 @@ import {
67
67
  } from '../sdk.gen'
68
68
  import type {
69
69
  AddPublishListMembersOperation,
70
+ AssociationResponse,
70
71
  AutoMapElementsOperation,
71
72
  ClosePeriodOperation,
72
73
  CreateAgentRequest,
@@ -79,18 +80,34 @@ import type {
79
80
  CreateTaxonomyBlockRequest,
80
81
  CreateViewRequest,
81
82
  DeleteInformationBlockRequest,
83
+ DeleteInformationBlockResponse,
82
84
  DeleteJournalEntryRequest,
83
85
  DeleteMappingAssociationOperation,
86
+ DeleteResult,
84
87
  DeleteTaxonomyBlockRequest,
88
+ DeleteTaxonomyBlockResponse,
89
+ EntityTaxonomyResponse,
85
90
  EvaluateRulesRequest,
91
+ EvaluateRulesResponse,
92
+ EventBlockEnvelope,
93
+ EventHandlerResponse,
86
94
  FileReportRequest,
87
95
  FinancialStatementAnalysisRequest,
96
+ InformationBlockEnvelope,
88
97
  InitializeLedgerRequest,
98
+ JournalEntryResponse,
99
+ LedgerAgentResponse,
89
100
  LinkEntityTaxonomyRequest,
90
101
  LiveFinancialStatementRequest,
91
102
  OperationEnvelope,
103
+ PreviewEventBlockResponse,
104
+ PublishListMemberResponse,
105
+ PublishListResponse,
92
106
  ReopenPeriodOperation,
107
+ ReportResponse,
93
108
  SetCloseTargetOperation,
109
+ ShareReportResponse,
110
+ TaxonomyBlockEnvelope,
94
111
  TransitionFilingStatusRequest,
95
112
  UpdateAgentRequest,
96
113
  UpdateEntityRequest,
@@ -277,10 +294,17 @@ export interface CreateReportOptions {
277
294
  periods?: PeriodSpecInput[]
278
295
  }
279
296
 
280
- export interface ReportOperationAck {
297
+ /**
298
+ * Wrapper returned by report write methods — pairs the audit-side
299
+ * envelope fields (`operationId`, `status`) with the typed result
300
+ * payload. Generic on ``T`` so each method advertises its specific
301
+ * result type (e.g. ``ReportResponse`` for creates, ``DeleteResult``
302
+ * for deletes).
303
+ */
304
+ export interface ReportOperationAck<T = unknown> {
281
305
  operationId: string
282
306
  status: OperationEnvelope['status']
283
- result: Record<string, unknown> | null
307
+ result: T | null
284
308
  }
285
309
 
286
310
  // ── Write result shapes (envelope.result payloads) ─────────────────────
@@ -406,6 +430,13 @@ export interface CreateJournalEntryOptions {
406
430
  type?: LedgerEntryType
407
431
  status?: 'draft' | 'posted'
408
432
  transactionId?: string | null
433
+ /**
434
+ * Who fired the event. Defaults to `'manual'` (user-initiated journal
435
+ * entry). Sync adapters (QuickBooks, Plaid, etc.) override with their
436
+ * adapter name. Must match the server's CHECK constraint set:
437
+ * `manual | schedule | system | quickbooks | xero | plaid`.
438
+ */
439
+ source?: string
409
440
  idempotencyKey?: string | null
410
441
  }
411
442
 
@@ -756,12 +787,12 @@ export class LedgerClient {
756
787
  async linkEntityTaxonomy(
757
788
  graphId: string,
758
789
  body: LinkEntityTaxonomyRequest
759
- ): Promise<Record<string, unknown>> {
790
+ ): Promise<EntityTaxonomyResponse> {
760
791
  const envelope = await this.callOperation(
761
792
  'Link entity taxonomy',
762
793
  opLinkEntityTaxonomy({ path: { graph_id: graphId }, body })
763
794
  )
764
- return (envelope.result ?? {}) as Record<string, unknown>
795
+ return this.requireResult('Link entity taxonomy', envelope.result)
765
796
  }
766
797
 
767
798
  /**
@@ -772,37 +803,37 @@ export class LedgerClient {
772
803
  graphId: string,
773
804
  body: CreateTaxonomyBlockRequest,
774
805
  idempotencyKey?: string
775
- ): Promise<Record<string, unknown>> {
806
+ ): Promise<TaxonomyBlockEnvelope> {
776
807
  const headers = idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : undefined
777
808
  const envelope = await this.callOperation(
778
809
  'Create taxonomy block',
779
810
  opCreateTaxonomyBlock({ path: { graph_id: graphId }, body, headers })
780
811
  )
781
- return (envelope.result ?? {}) as Record<string, unknown>
812
+ return this.requireResult('Create taxonomy block', envelope.result)
782
813
  }
783
814
 
784
815
  /** Update a taxonomy block — add/update/remove elements, structures, associations, or rules. */
785
816
  async updateTaxonomyBlock(
786
817
  graphId: string,
787
818
  body: UpdateTaxonomyBlockRequest
788
- ): Promise<Record<string, unknown>> {
819
+ ): Promise<TaxonomyBlockEnvelope> {
789
820
  const envelope = await this.callOperation(
790
821
  'Update taxonomy block',
791
822
  opUpdateTaxonomyBlock({ path: { graph_id: graphId }, body })
792
823
  )
793
- return (envelope.result ?? {}) as Record<string, unknown>
824
+ return this.requireResult('Update taxonomy block', envelope.result)
794
825
  }
795
826
 
796
827
  /** Delete a taxonomy block. Cascades through elements, structures, and associations. */
797
828
  async deleteTaxonomyBlock(
798
829
  graphId: string,
799
830
  body: DeleteTaxonomyBlockRequest
800
- ): Promise<{ deleted: boolean }> {
831
+ ): Promise<DeleteTaxonomyBlockResponse> {
801
832
  const envelope = await this.callOperation(
802
833
  'Delete taxonomy block',
803
834
  opDeleteTaxonomyBlock({ path: { graph_id: graphId }, body })
804
835
  )
805
- return (envelope.result ?? { deleted: true }) as { deleted: boolean }
836
+ return (envelope.result ?? { deleted: true }) as DeleteTaxonomyBlockResponse
806
837
  }
807
838
 
808
839
  /** List elements (CoA accounts, GAAP concepts, etc.) with filters. */
@@ -910,24 +941,24 @@ export class LedgerClient {
910
941
  async createMappingAssociation(
911
942
  graphId: string,
912
943
  body: CreateMappingAssociationOperation
913
- ): Promise<Record<string, unknown>> {
944
+ ): Promise<AssociationResponse> {
914
945
  const envelope = await this.callOperation(
915
946
  'Create mapping association',
916
947
  opCreateMappingAssociation({ path: { graph_id: graphId }, body })
917
948
  )
918
- return (envelope.result ?? {}) as Record<string, unknown>
949
+ return this.requireResult('Create mapping association', envelope.result)
919
950
  }
920
951
 
921
952
  /** Delete a mapping association. */
922
953
  async deleteMappingAssociation(
923
954
  graphId: string,
924
955
  body: DeleteMappingAssociationOperation
925
- ): Promise<{ deleted: boolean }> {
956
+ ): Promise<DeleteResult> {
926
957
  const envelope = await this.callOperation(
927
958
  'Delete mapping association',
928
959
  opDeleteMappingAssociation({ path: { graph_id: graphId }, body })
929
960
  )
930
- return (envelope.result ?? { deleted: true }) as { deleted: boolean }
961
+ return (envelope.result ?? { deleted: true }) as DeleteResult
931
962
  }
932
963
 
933
964
  /**
@@ -1042,7 +1073,7 @@ export class LedgerClient {
1042
1073
  graphId: string,
1043
1074
  structureId: string,
1044
1075
  options: { name?: string }
1045
- ): Promise<Record<string, unknown>> {
1076
+ ): Promise<InformationBlockEnvelope> {
1046
1077
  const body: UpdateInformationBlockRequest = {
1047
1078
  block_type: 'schedule',
1048
1079
  payload: { structure_id: structureId, ...options },
@@ -1051,11 +1082,14 @@ export class LedgerClient {
1051
1082
  'Update schedule',
1052
1083
  opUpdateInformationBlock({ path: { graph_id: graphId }, body })
1053
1084
  )
1054
- return (envelope.result ?? {}) as Record<string, unknown>
1085
+ return this.requireResult('Update schedule', envelope.result)
1055
1086
  }
1056
1087
 
1057
1088
  /** Permanently delete a schedule (cascades through facts + associations). */
1058
- async deleteSchedule(graphId: string, structureId: string): Promise<{ deleted: boolean }> {
1089
+ async deleteSchedule(
1090
+ graphId: string,
1091
+ structureId: string
1092
+ ): Promise<DeleteInformationBlockResponse> {
1059
1093
  const body: DeleteInformationBlockRequest = {
1060
1094
  block_type: 'schedule',
1061
1095
  payload: { structure_id: structureId },
@@ -1064,7 +1098,7 @@ export class LedgerClient {
1064
1098
  'Delete schedule',
1065
1099
  opDeleteInformationBlock({ path: { graph_id: graphId }, body })
1066
1100
  )
1067
- return (envelope.result ?? { deleted: true }) as { deleted: boolean }
1101
+ return (envelope.result ?? { deleted: true }) as DeleteInformationBlockResponse
1068
1102
  }
1069
1103
 
1070
1104
  /**
@@ -1073,6 +1107,8 @@ export class LedgerClient {
1073
1107
  *
1074
1108
  * Routes through `create-event-block` with `event_type='asset_disposed'`.
1075
1109
  * `occurred_at` is required and represents the disposal date.
1110
+ * `source` defaults to `'manual'` (user-initiated disposal); sync
1111
+ * adapters override.
1076
1112
  */
1077
1113
  async disposeSchedule(
1078
1114
  graphId: string,
@@ -1084,12 +1120,13 @@ export class LedgerClient {
1084
1120
  gainLossElementId?: string | null
1085
1121
  memo?: string | null
1086
1122
  reason?: string
1123
+ source?: string
1087
1124
  }
1088
- ): Promise<Record<string, unknown>> {
1125
+ ): Promise<EventBlockEnvelope> {
1089
1126
  const body: CreateEventBlockRequest = {
1090
1127
  event_type: 'asset_disposed',
1091
1128
  event_category: 'adjustment',
1092
- source: 'native',
1129
+ source: options.source ?? 'manual',
1093
1130
  occurred_at: options.occurredAt,
1094
1131
  apply_handlers: true,
1095
1132
  metadata: {
@@ -1105,19 +1142,16 @@ export class LedgerClient {
1105
1142
  'Dispose schedule',
1106
1143
  opCreateEventBlock({ path: { graph_id: graphId }, body })
1107
1144
  )
1108
- return (envelope.result ?? {}) as Record<string, unknown>
1145
+ return this.requireResult('Dispose schedule', envelope.result)
1109
1146
  }
1110
1147
 
1111
1148
  /** Evaluate taxonomy rules against facts in a structure. */
1112
- async evaluateRules(
1113
- graphId: string,
1114
- body: EvaluateRulesRequest
1115
- ): Promise<Record<string, unknown>> {
1149
+ async evaluateRules(graphId: string, body: EvaluateRulesRequest): Promise<EvaluateRulesResponse> {
1116
1150
  const envelope = await this.callOperation(
1117
1151
  'Evaluate rules',
1118
1152
  opEvaluateRules({ path: { graph_id: graphId }, body })
1119
1153
  )
1120
- return (envelope.result ?? {}) as Record<string, unknown>
1154
+ return this.requireResult('Evaluate rules', envelope.result)
1121
1155
  }
1122
1156
 
1123
1157
  // ── Period close ────────────────────────────────────────────────────
@@ -1164,11 +1198,12 @@ export class LedgerClient {
1164
1198
  periodStart: string,
1165
1199
  periodEnd: string,
1166
1200
  memo?: string
1167
- ): Promise<Record<string, unknown>> {
1201
+ ): Promise<EventBlockEnvelope> {
1168
1202
  const body: CreateEventBlockRequest = {
1169
1203
  event_type: 'schedule_entry_due',
1170
1204
  event_category: 'recognition',
1171
- source: 'scheduled',
1205
+ // Always 'schedule' — this op is schedule-driven by definition.
1206
+ source: 'schedule',
1172
1207
  occurred_at: `${postingDate}T00:00:00Z`,
1173
1208
  apply_handlers: true,
1174
1209
  metadata: {
@@ -1183,7 +1218,7 @@ export class LedgerClient {
1183
1218
  'Create closing entry',
1184
1219
  opCreateEventBlock({ path: { graph_id: graphId }, body })
1185
1220
  )
1186
- return (envelope.result ?? {}) as Record<string, unknown>
1221
+ return this.requireResult('Create closing entry', envelope.result)
1187
1222
  }
1188
1223
 
1189
1224
  // ── Closing book ───────────────────────────────────────────────────
@@ -1313,11 +1348,11 @@ export class LedgerClient {
1313
1348
  async createJournalEntry(
1314
1349
  graphId: string,
1315
1350
  options: CreateJournalEntryOptions
1316
- ): Promise<Record<string, unknown>> {
1351
+ ): Promise<EventBlockEnvelope> {
1317
1352
  const body: CreateEventBlockRequest = {
1318
1353
  event_type: 'journal_entry_recorded',
1319
1354
  event_category: 'adjustment',
1320
- source: 'native',
1355
+ source: options.source ?? 'manual',
1321
1356
  occurred_at: `${options.postingDate}T00:00:00Z`,
1322
1357
  apply_handlers: true,
1323
1358
  metadata: {
@@ -1341,29 +1376,29 @@ export class LedgerClient {
1341
1376
  'Create journal entry',
1342
1377
  opCreateEventBlock({ path: { graph_id: graphId }, body, headers })
1343
1378
  )
1344
- return (envelope.result ?? {}) as Record<string, unknown>
1379
+ return this.requireResult('Create journal entry', envelope.result)
1345
1380
  }
1346
1381
 
1347
1382
  /** Update a draft journal entry. Posted entries are immutable. */
1348
1383
  async updateJournalEntry(
1349
1384
  graphId: string,
1350
1385
  body: UpdateJournalEntryRequest
1351
- ): Promise<Record<string, unknown>> {
1386
+ ): Promise<JournalEntryResponse> {
1352
1387
  const envelope = await this.callOperation(
1353
1388
  'Update journal entry',
1354
1389
  opUpdateJournalEntry({ path: { graph_id: graphId }, body })
1355
1390
  )
1356
- return (envelope.result ?? {}) as Record<string, unknown>
1391
+ return this.requireResult('Update journal entry', envelope.result)
1357
1392
  }
1358
1393
 
1359
1394
  /** Hard-delete a draft journal entry. Posted entries must be reversed. */
1360
- async deleteJournalEntry(graphId: string, entryId: string): Promise<{ deleted: boolean }> {
1395
+ async deleteJournalEntry(graphId: string, entryId: string): Promise<DeleteResult> {
1361
1396
  const body: DeleteJournalEntryRequest = { entry_id: entryId }
1362
1397
  const envelope = await this.callOperation(
1363
1398
  'Delete journal entry',
1364
1399
  opDeleteJournalEntry({ path: { graph_id: graphId }, body })
1365
1400
  )
1366
- return (envelope.result ?? { deleted: true }) as { deleted: boolean }
1401
+ return (envelope.result ?? { deleted: true }) as DeleteResult
1367
1402
  }
1368
1403
 
1369
1404
  /**
@@ -1371,7 +1406,8 @@ export class LedgerClient {
1371
1406
  * the original as reversed.
1372
1407
  *
1373
1408
  * Routes through `create-event-block` with
1374
- * `event_type='journal_entry_reversed'`.
1409
+ * `event_type='journal_entry_reversed'`. `source` defaults to `'manual'`
1410
+ * — sync adapters override.
1375
1411
  */
1376
1412
  async reverseJournalEntry(
1377
1413
  graphId: string,
@@ -1380,13 +1416,14 @@ export class LedgerClient {
1380
1416
  postingDate?: string | null
1381
1417
  memo?: string | null
1382
1418
  reason?: string | null
1419
+ source?: string
1383
1420
  }
1384
- ): Promise<Record<string, unknown>> {
1421
+ ): Promise<EventBlockEnvelope> {
1385
1422
  const occurredDate = options?.postingDate ?? new Date().toISOString().slice(0, 10)
1386
1423
  const body: CreateEventBlockRequest = {
1387
1424
  event_type: 'journal_entry_reversed',
1388
1425
  event_category: 'adjustment',
1389
- source: 'native',
1426
+ source: options?.source ?? 'manual',
1390
1427
  occurred_at: `${occurredDate}T00:00:00Z`,
1391
1428
  apply_handlers: true,
1392
1429
  metadata: {
@@ -1400,7 +1437,7 @@ export class LedgerClient {
1400
1437
  'Reverse journal entry',
1401
1438
  opCreateEventBlock({ path: { graph_id: graphId }, body })
1402
1439
  )
1403
- return (envelope.result ?? {}) as Record<string, unknown>
1440
+ return this.requireResult('Reverse journal entry', envelope.result)
1404
1441
  }
1405
1442
 
1406
1443
  // ── Event blocks (generic preview + status transitions) ──────────────
@@ -1416,12 +1453,12 @@ export class LedgerClient {
1416
1453
  async previewEventBlock(
1417
1454
  graphId: string,
1418
1455
  body: CreateEventBlockRequest
1419
- ): Promise<Record<string, unknown>> {
1456
+ ): Promise<PreviewEventBlockResponse> {
1420
1457
  const envelope = await this.callOperation(
1421
1458
  'Preview event block',
1422
1459
  opPreviewEventBlock({ path: { graph_id: graphId }, body })
1423
1460
  )
1424
- return (envelope.result ?? {}) as Record<string, unknown>
1461
+ return this.requireResult('Preview event block', envelope.result)
1425
1462
  }
1426
1463
 
1427
1464
  /**
@@ -1433,12 +1470,12 @@ export class LedgerClient {
1433
1470
  async updateEventBlock(
1434
1471
  graphId: string,
1435
1472
  body: UpdateEventBlockRequest
1436
- ): Promise<Record<string, unknown>> {
1473
+ ): Promise<EventBlockEnvelope> {
1437
1474
  const envelope = await this.callOperation(
1438
1475
  'Update event block',
1439
1476
  opUpdateEventBlock({ path: { graph_id: graphId }, body })
1440
1477
  )
1441
- return (envelope.result ?? {}) as Record<string, unknown>
1478
+ return this.requireResult('Update event block', envelope.result)
1442
1479
  }
1443
1480
 
1444
1481
  // ── Agents (REA counterparties) ───────────────────────────────────────
@@ -1453,25 +1490,25 @@ export class LedgerClient {
1453
1490
  graphId: string,
1454
1491
  body: CreateAgentRequest,
1455
1492
  idempotencyKey?: string
1456
- ): Promise<Record<string, unknown>> {
1493
+ ): Promise<LedgerAgentResponse> {
1457
1494
  const headers = idempotencyKey ? { 'Idempotency-Key': idempotencyKey } : undefined
1458
1495
  const envelope = await this.callOperation(
1459
1496
  'Create agent',
1460
1497
  opCreateAgent({ path: { graph_id: graphId }, body, headers })
1461
1498
  )
1462
- return (envelope.result ?? {}) as Record<string, unknown>
1499
+ return this.requireResult('Create agent', envelope.result)
1463
1500
  }
1464
1501
 
1465
1502
  /**
1466
1503
  * Update an agent. `metadata_patch` is a partial merge into the existing
1467
1504
  * metadata object; all other fields replace.
1468
1505
  */
1469
- async updateAgent(graphId: string, body: UpdateAgentRequest): Promise<Record<string, unknown>> {
1506
+ async updateAgent(graphId: string, body: UpdateAgentRequest): Promise<LedgerAgentResponse> {
1470
1507
  const envelope = await this.callOperation(
1471
1508
  'Update agent',
1472
1509
  opUpdateAgent({ path: { graph_id: graphId }, body })
1473
1510
  )
1474
- return (envelope.result ?? {}) as Record<string, unknown>
1511
+ return this.requireResult('Update agent', envelope.result)
1475
1512
  }
1476
1513
 
1477
1514
  // ── Event handlers (DSL handler registry) ────────────────────────────
@@ -1485,12 +1522,12 @@ export class LedgerClient {
1485
1522
  async createEventHandler(
1486
1523
  graphId: string,
1487
1524
  body: CreateEventHandlerRequest
1488
- ): Promise<Record<string, unknown>> {
1525
+ ): Promise<EventHandlerResponse> {
1489
1526
  const envelope = await this.callOperation(
1490
1527
  'Create event handler',
1491
1528
  opCreateEventHandler({ path: { graph_id: graphId }, body })
1492
1529
  )
1493
- return (envelope.result ?? {}) as Record<string, unknown>
1530
+ return this.requireResult('Create event handler', envelope.result)
1494
1531
  }
1495
1532
 
1496
1533
  /**
@@ -1500,12 +1537,12 @@ export class LedgerClient {
1500
1537
  async updateEventHandler(
1501
1538
  graphId: string,
1502
1539
  body: UpdateEventHandlerRequest
1503
- ): Promise<Record<string, unknown>> {
1540
+ ): Promise<EventHandlerResponse> {
1504
1541
  const envelope = await this.callOperation(
1505
1542
  'Update event handler',
1506
1543
  opUpdateEventHandler({ path: { graph_id: graphId }, body })
1507
1544
  )
1508
- return (envelope.result ?? {}) as Record<string, unknown>
1545
+ return this.requireResult('Update event handler', envelope.result)
1509
1546
  }
1510
1547
 
1511
1548
  // ── Financial statements (graph-backed) ──────────────────────────────
@@ -1599,7 +1636,10 @@ export class LedgerClient {
1599
1636
  * Kick off report creation (async). Use the returned `operationId` to
1600
1637
  * subscribe to progress via SSE, then call `getReport()` once finished.
1601
1638
  */
1602
- async createReport(graphId: string, options: CreateReportOptions): Promise<ReportOperationAck> {
1639
+ async createReport(
1640
+ graphId: string,
1641
+ options: CreateReportOptions
1642
+ ): Promise<ReportOperationAck<ReportResponse>> {
1603
1643
  const body: CreateReportRequest = {
1604
1644
  name: options.name,
1605
1645
  mapping_id: options.mappingId,
@@ -1619,7 +1659,7 @@ export class LedgerClient {
1619
1659
  return {
1620
1660
  operationId: envelope.operationId,
1621
1661
  status: envelope.status,
1622
- result: (envelope.result as Record<string, unknown> | null) ?? null,
1662
+ result: envelope.result ?? null,
1623
1663
  }
1624
1664
  }
1625
1665
 
@@ -1690,7 +1730,7 @@ export class LedgerClient {
1690
1730
  reportId: string,
1691
1731
  periodStart?: string,
1692
1732
  periodEnd?: string
1693
- ): Promise<ReportOperationAck> {
1733
+ ): Promise<ReportOperationAck<ReportResponse>> {
1694
1734
  const envelope = await this.callOperation(
1695
1735
  'Regenerate report',
1696
1736
  opRegenerateReport({
@@ -1705,30 +1745,31 @@ export class LedgerClient {
1705
1745
  return {
1706
1746
  operationId: envelope.operationId,
1707
1747
  status: envelope.status,
1708
- result: (envelope.result as Record<string, unknown> | null) ?? null,
1748
+ result: envelope.result ?? null,
1709
1749
  }
1710
1750
  }
1711
1751
 
1712
1752
  /** Delete a report and its generated facts. */
1713
- async deleteReport(graphId: string, reportId: string): Promise<void> {
1714
- await this.callOperation(
1753
+ async deleteReport(graphId: string, reportId: string): Promise<DeleteResult> {
1754
+ const envelope = await this.callOperation(
1715
1755
  'Delete report',
1716
1756
  opDeleteReport({
1717
1757
  path: { graph_id: graphId },
1718
1758
  body: { report_id: reportId },
1719
1759
  })
1720
1760
  )
1761
+ return (envelope.result ?? { deleted: true }) as DeleteResult
1721
1762
  }
1722
1763
 
1723
1764
  /**
1724
- * Share a published report to every member of a publish list (async).
1725
- * Each target graph receives a snapshot copy of the report's facts.
1765
+ * Share a published report to every member of a publish list. Each
1766
+ * target graph receives a snapshot copy of the report's facts.
1726
1767
  */
1727
1768
  async shareReport(
1728
1769
  graphId: string,
1729
1770
  reportId: string,
1730
1771
  publishListId: string
1731
- ): Promise<ReportOperationAck> {
1772
+ ): Promise<ReportOperationAck<ShareReportResponse>> {
1732
1773
  const envelope = await this.callOperation(
1733
1774
  'Share report',
1734
1775
  opShareReport({
@@ -1742,7 +1783,7 @@ export class LedgerClient {
1742
1783
  return {
1743
1784
  operationId: envelope.operationId,
1744
1785
  status: envelope.status,
1745
- result: (envelope.result as Record<string, unknown> | null) ?? null,
1786
+ result: envelope.result ?? null,
1746
1787
  }
1747
1788
  }
1748
1789
 
@@ -1751,7 +1792,7 @@ export class LedgerClient {
1751
1792
  * Allowed from 'draft' or 'under_review'. Stamps filed_at + filed_by
1752
1793
  * from the auth context + server clock.
1753
1794
  */
1754
- async fileReport(graphId: string, reportId: string): Promise<ReportOperationAck> {
1795
+ async fileReport(graphId: string, reportId: string): Promise<ReportOperationAck<ReportResponse>> {
1755
1796
  const body: FileReportRequest = { report_id: reportId }
1756
1797
  const envelope = await this.callOperation(
1757
1798
  'File report',
@@ -1760,7 +1801,7 @@ export class LedgerClient {
1760
1801
  return {
1761
1802
  operationId: envelope.operationId,
1762
1803
  status: envelope.status,
1763
- result: (envelope.result as Record<string, unknown> | null) ?? null,
1804
+ result: envelope.result ?? null,
1764
1805
  }
1765
1806
  }
1766
1807
 
@@ -1773,7 +1814,7 @@ export class LedgerClient {
1773
1814
  graphId: string,
1774
1815
  reportId: string,
1775
1816
  targetStatus: string
1776
- ): Promise<ReportOperationAck> {
1817
+ ): Promise<ReportOperationAck<ReportResponse>> {
1777
1818
  const body: TransitionFilingStatusRequest = {
1778
1819
  report_id: reportId,
1779
1820
  target_status: targetStatus,
@@ -1785,7 +1826,7 @@ export class LedgerClient {
1785
1826
  return {
1786
1827
  operationId: envelope.operationId,
1787
1828
  status: envelope.status,
1788
- result: (envelope.result as Record<string, unknown> | null) ?? null,
1829
+ result: envelope.result ?? null,
1789
1830
  }
1790
1831
  }
1791
1832
 
@@ -1819,7 +1860,7 @@ export class LedgerClient {
1819
1860
  graphId: string,
1820
1861
  name: string,
1821
1862
  description?: string
1822
- ): Promise<Record<string, unknown>> {
1863
+ ): Promise<PublishListResponse> {
1823
1864
  const body: CreatePublishListRequest = {
1824
1865
  name,
1825
1866
  description: description ?? null,
@@ -1828,7 +1869,7 @@ export class LedgerClient {
1828
1869
  'Create publish list',
1829
1870
  opCreatePublishList({ path: { graph_id: graphId }, body })
1830
1871
  )
1831
- return (envelope.result ?? {}) as Record<string, unknown>
1872
+ return this.requireResult('Create publish list', envelope.result)
1832
1873
  }
1833
1874
 
1834
1875
  /** Get a single publish list with its full member list. */
@@ -1847,7 +1888,7 @@ export class LedgerClient {
1847
1888
  graphId: string,
1848
1889
  listId: string,
1849
1890
  updates: { name?: string; description?: string | null }
1850
- ): Promise<Record<string, unknown>> {
1891
+ ): Promise<PublishListResponse> {
1851
1892
  const envelope = await this.callOperation(
1852
1893
  'Update publish list',
1853
1894
  opUpdatePublishList({
@@ -1859,18 +1900,19 @@ export class LedgerClient {
1859
1900
  } as UpdatePublishListOperation,
1860
1901
  })
1861
1902
  )
1862
- return (envelope.result ?? {}) as Record<string, unknown>
1903
+ return this.requireResult('Update publish list', envelope.result)
1863
1904
  }
1864
1905
 
1865
1906
  /** Delete a publish list. */
1866
- async deletePublishList(graphId: string, listId: string): Promise<void> {
1867
- await this.callOperation(
1907
+ async deletePublishList(graphId: string, listId: string): Promise<DeleteResult> {
1908
+ const envelope = await this.callOperation(
1868
1909
  'Delete publish list',
1869
1910
  opDeletePublishList({
1870
1911
  path: { graph_id: graphId },
1871
1912
  body: { list_id: listId },
1872
1913
  })
1873
1914
  )
1915
+ return (envelope.result ?? { deleted: true }) as DeleteResult
1874
1916
  }
1875
1917
 
1876
1918
  /** Add target graphs as members of a publish list. */
@@ -1878,7 +1920,7 @@ export class LedgerClient {
1878
1920
  graphId: string,
1879
1921
  listId: string,
1880
1922
  targetGraphIds: string[]
1881
- ): Promise<Record<string, unknown>> {
1923
+ ): Promise<PublishListMemberResponse[]> {
1882
1924
  const envelope = await this.callOperation(
1883
1925
  'Add publish list members',
1884
1926
  opAddPublishListMembers({
@@ -1889,7 +1931,7 @@ export class LedgerClient {
1889
1931
  } as AddPublishListMembersOperation,
1890
1932
  })
1891
1933
  )
1892
- return (envelope.result ?? {}) as Record<string, unknown>
1934
+ return this.requireResult('Add publish list members', envelope.result)
1893
1935
  }
1894
1936
 
1895
1937
  /** Remove a single member from a publish list. */
@@ -1897,7 +1939,7 @@ export class LedgerClient {
1897
1939
  graphId: string,
1898
1940
  listId: string,
1899
1941
  memberId: string
1900
- ): Promise<{ deleted: boolean }> {
1942
+ ): Promise<DeleteResult> {
1901
1943
  const envelope = await this.callOperation(
1902
1944
  'Remove publish list member',
1903
1945
  opRemovePublishListMember({
@@ -1905,19 +1947,25 @@ export class LedgerClient {
1905
1947
  body: { list_id: listId, member_id: memberId },
1906
1948
  })
1907
1949
  )
1908
- return (envelope.result ?? { deleted: true }) as { deleted: boolean }
1950
+ return (envelope.result ?? { deleted: true }) as DeleteResult
1909
1951
  }
1910
1952
 
1911
1953
  // ── Internal helpers ────────────────────────────────────────────────
1912
1954
 
1913
1955
  /**
1914
1956
  * Await an SDK-generated `opXxx(...)` call, throw a readable error on
1915
- * non-2xx, and return the `OperationEnvelope` on success.
1957
+ * non-2xx, and return the parsed envelope on success.
1958
+ *
1959
+ * Generic over the SDK call's response shape so typed ops (e.g.
1960
+ * `opCreateEventBlock`, which returns
1961
+ * `OperationEnvelopeEventBlockEnvelope`) flow through with a typed
1962
+ * `envelope.result` instead of being widened to `unknown`. Untyped
1963
+ * ops continue to land as `OperationEnvelope` automatically.
1916
1964
  */
1917
- private async callOperation(
1965
+ private async callOperation<T>(
1918
1966
  label: string,
1919
- call: Promise<{ data?: OperationEnvelope; error?: unknown }>
1920
- ): Promise<OperationEnvelope> {
1967
+ call: Promise<{ data?: T; error?: unknown }>
1968
+ ): Promise<T> {
1921
1969
  const response = await call
1922
1970
  if (response.error !== undefined) {
1923
1971
  throw new Error(`${label} failed: ${JSON.stringify(response.error)}`)
@@ -1927,6 +1975,18 @@ export class LedgerClient {
1927
1975
  }
1928
1976
  return response.data
1929
1977
  }
1978
+
1979
+ /**
1980
+ * Unwrap the typed result from an OperationEnvelope. Throws when the
1981
+ * server returned an envelope with no `result` field — generally a
1982
+ * sign that a synchronous operation failed silently.
1983
+ */
1984
+ private requireResult<T>(label: string, result: T | null | undefined): T {
1985
+ if (result === null || result === undefined) {
1986
+ throw new Error(`${label}: operation envelope had no result`)
1987
+ }
1988
+ return result
1989
+ }
1930
1990
  }
1931
1991
 
1932
1992
  // ── Module-private conversion helpers ─────────────────────────────────