@acosmi/sdk-ts 1.4.2 → 1.5.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.
@@ -90,6 +90,17 @@ Report scopes are split by action:
90
90
  again) so the new scope is granted.
91
91
  - `ScopeComplianceReportsPublish` — `publishReport` (also requires step-up).
92
92
 
93
+ Contract-template scopes (added in v1.10.0) are split by direction and do not
94
+ require step-up:
95
+
96
+ - `ScopeComplianceContractTemplateRead` — `getContractTemplate`,
97
+ `listContractTemplates`, `listContractTemplateVersions`.
98
+ - `ScopeComplianceContractTemplateWrite` — `createContractTemplate`,
99
+ `updateContractTemplate`, `deleteContractTemplate`,
100
+ `uploadContractTemplatePdf`, `publishContractTemplate`,
101
+ `archiveContractTemplate`. Tokens issued before v1.10.0 do **not** carry these
102
+ scopes; existing users must re-authorize so the new scopes are granted.
103
+
93
104
  ## Base URL
94
105
 
95
106
  `Client` keeps the existing model gateway path under `/api/v4`. Compliance uses
@@ -231,6 +242,398 @@ if (view.status === 'SUCCESS') {
231
242
  }
232
243
  ```
233
244
 
245
+ ## Paginated Lists
246
+
247
+ Since v1.6.0 the SDK exposes paginated list reads against the backend
248
+ compliance gateway (`GET .../page`). Each returns a yudao `PageResult<T>`
249
+ (`{ total, list }` — the single SDK-wide pagination result shape, an alias of
250
+ `YudaoPageResult<T>`):
251
+
252
+ ```ts
253
+ import type { PageResult, EvidenceAssetPageItem } from '@acosmi/sdk-ts';
254
+
255
+ client.compliance.listEvidenceAssets(req?, signal?): Promise<PageResult<EvidenceAssetPageItem>>;
256
+ client.compliance.listTimestamps(req?, signal?): Promise<PageResult<TimestampPageItem>>;
257
+ client.compliance.listEvidencePackages(req?, signal?): Promise<PageResult<EvidencePackagePageItem>>;
258
+ client.compliance.listReports(req?, signal?): Promise<PageResult<ReportPageItem>>;
259
+ client.compliance.listSigningEnvelopes(req?, signal?): Promise<PageResult<SigningEnvelopePageItem>>;
260
+ client.compliance.listSealApprovals(req?, signal?): Promise<PageResult<SealApprovalPageItem>>;
261
+ client.compliance.listSealUses(req?, signal?): Promise<PageResult<SealUsePageItem>>;
262
+ ```
263
+
264
+ The request argument is optional. It extends the shared `PageRequest`
265
+ (`pageNo`, `pageSize`, `sortBy`, `sortDirection` — all optional; omitted values
266
+ let the backend pick defaults) plus per-method filters:
267
+
268
+ | Method | Endpoint | Filters (all optional) |
269
+ | --- | --- | --- |
270
+ | `listEvidenceAssets` | `GET /compliance/evidence/assets/page` | `assetType`, `status`, `createTimeStart`, `createTimeEnd` |
271
+ | `listTimestamps` | `GET /compliance/timestamps/page` | `provider`, `verificationStatus`, `createTimeStart`, `createTimeEnd` |
272
+ | `listEvidencePackages` | `GET /compliance/evidence/packages/page` | `status`, `createTimeStart`, `createTimeEnd` |
273
+ | `listReports` | `GET /compliance/reports/page` | `status`, `createTimeStart`, `createTimeEnd` |
274
+ | `listSigningEnvelopes` | `GET /compliance/signing-envelopes/page` | `status`, `createTimeStart`, `createTimeEnd` |
275
+ | `listSealApprovals` | `GET /compliance/seal-approvals/page` | `status`, `createTimeStart`, `createTimeEnd` |
276
+ | `listSealUses` | `GET /compliance/seal-uses/page` | `sealId`, `envelopeId`, `usageStatus`, `createTimeStart`, `createTimeEnd` |
277
+
278
+ `createTimeStart` / `createTimeEnd` are caller-supplied datetime **strings**. The
279
+ backend parses them as `yyyy-MM-dd HH:mm:ss` (for example
280
+ `'2026-05-01 00:00:00'`). The SDK passes them through verbatim — it does not
281
+ validate the format or convert time zones.
282
+
283
+ ```ts
284
+ const page = await client.compliance.listSealApprovals({
285
+ pageNo: 1,
286
+ pageSize: 20,
287
+ status: 'PENDING',
288
+ createTimeStart: '2026-05-01 00:00:00',
289
+ createTimeEnd: '2026-05-22 23:59:59',
290
+ });
291
+
292
+ console.log(page.total, page.list.length);
293
+ ```
294
+
295
+ These are authenticated GET reads, so they follow the same read semantics as
296
+ `getEvidenceAsset` / `getReport`: one safe `401` refresh-and-replay retry.
297
+
298
+ `listSealApprovals` is distinct from `listPendingSealApprovals` — the latter
299
+ returns only pending approvals as a plain array; `listSealApprovals` is paginated
300
+ and supports status / time filtering.
301
+
302
+ The `*PageItem` types (`EvidenceAssetPageItem`, `TimestampPageItem`,
303
+ `EvidencePackagePageItem`, `ReportPageItem`, `SigningEnvelopePageItem`,
304
+ `SealApprovalPageItem`, `SealUsePageItem`) are the SDK-safe subset of the
305
+ corresponding detail view plus a `createTime` (ISO-8601) field. They never
306
+ expose provider raw payloads, certificates, storage keys, or contract originals.
307
+
308
+ `listSealUses` (compliance gateway S6) returns one row per **seal use** — the
309
+ real `provider`-side seal application that fires after envelope / contract /
310
+ seal / approval are linked. It is orthogonal to the envelope domain status and
311
+ to the seal-approval workflow:
312
+
313
+ - `listSigningEnvelopes` → high-level envelope domain state.
314
+ - `listSealApprovals` → the approval workflow on an envelope (`PENDING` →
315
+ `APPROVED` / `REJECTED` / `CANCELED`).
316
+ - `listSealUses` → the actual seal-application execution
317
+ (`invokedAt` → `consumedAt`, with `failureReason` on terminal failure).
318
+
319
+ `SealUsePageItem` fields: `id` (number), `envelopeId` (number), `contractId`
320
+ (number), `sealId` (number), `usageStatus` (string), `signLocationType`
321
+ (string?), `invokedAt` (string?), `consumedAt` (string?), `failureReason`
322
+ (string?), `createTime` (string — ISO-8601).
323
+
324
+ `listSealUses` reuses the existing read scope
325
+ `ScopeComplianceContractSigningRead` (`compliance:contract_signing:read`); it
326
+ does not introduce a new scope. The seal authorization surface and the full
327
+ seal CRUD (gap-register U-3 / U-11) remain backend-deferred behind the CFCA
328
+ private jar and the W3 gate, and are not exposed as SDK methods in this
329
+ release.
330
+
331
+ ## Capabilities And Operation Projection
332
+
333
+ Since v1.7.0 the SDK exposes the compliance gateway S2 reads: a capability gate
334
+ query and an operation-projection view.
335
+
336
+ ```ts
337
+ client.compliance.getCapabilities(signal?): Promise<ComplianceCapability[]>;
338
+ client.compliance.getFeatureGate(action, signal?): Promise<ComplianceCapability | undefined>;
339
+ client.compliance.listOperations(req?, signal?): Promise<PageResult<OperationPageItem>>;
340
+ client.compliance.getOperation(id, signal?): Promise<OperationDetail>;
341
+ ```
342
+
343
+ All four are authenticated GET reads — they follow the same read semantics as
344
+ `getReport` / `getEvidenceAsset`: one safe `401` refresh-and-replay retry.
345
+
346
+ ### Capabilities
347
+
348
+ `getCapabilities` returns one `ComplianceCapability` entry per high-risk /
349
+ billed action: `signEnvelope`, `createH5SigningUrl`, `publishReport`,
350
+ `approveSealApproval`, `executeSealUse`, `createSeal`.
351
+
352
+ ```ts
353
+ const caps = await client.compliance.getCapabilities();
354
+ for (const cap of caps) {
355
+ console.log(cap.action, cap.executable, cap.state, cap.requiredScopes);
356
+ }
357
+ ```
358
+
359
+ `ComplianceCapability` fields: `action` (string), `executable` (boolean),
360
+ `state` (`executable` / `scope_missing` / `not_provisioned` /
361
+ `step_up_required` / `gate_closed` / `unknown` — reuses the cross-domain
362
+ `FeatureGateState` open union), `requiredScopes` (string[]), `requiredStepUp`
363
+ (boolean), `reason` (string).
364
+
365
+ Query the capability **before** invoking a high-risk action and gate the UI on
366
+ it. When the capability cannot be fetched, fail-closed — treat the action as
367
+ `executable: false`.
368
+
369
+ `getFeatureGate` is a convenience that fetches `getCapabilities` and returns the
370
+ entry whose `action` matches (or `undefined` when none match). **Each call makes
371
+ one network request.** To gate several actions, call `getCapabilities` once and
372
+ look them up locally instead of calling `getFeatureGate` repeatedly.
373
+
374
+ ```ts
375
+ const gate = await client.compliance.getFeatureGate('publishReport');
376
+ if (!gate || !gate.executable) {
377
+ if (gate?.state === 'step_up_required') {
378
+ await promptUserToReauthenticate();
379
+ }
380
+ return; // fail-closed
381
+ }
382
+ ```
383
+
384
+ ### Operation Projection
385
+
386
+ The operation projection describes the progress of a single operation — it is
387
+ orthogonal to a fulfillment object's domain status.
388
+
389
+ ```ts
390
+ const page = await client.compliance.listOperations({
391
+ pageNo: 1,
392
+ pageSize: 20,
393
+ status: 'failed',
394
+ createTimeStart: '2026-05-01 00:00:00',
395
+ createTimeEnd: '2026-05-22 23:59:59',
396
+ });
397
+
398
+ for (const op of page.list) {
399
+ console.log(op.id, op.operationId, op.status, op.terminal, op.retryable);
400
+ }
401
+
402
+ const detail = await client.compliance.getOperation(page.list[0].id);
403
+ ```
404
+
405
+ `listOperations` (`GET /compliance/operations/page`) returns a yudao
406
+ `PageResult<OperationPageItem>`. Its request extends the shared `PageRequest`
407
+ plus the optional `status` / `createTimeStart` / `createTimeEnd` filters.
408
+ `getOperation` (`GET /compliance/operations/{id}`) takes the numeric **row id**
409
+ (not the `operationId` idempotency key) and returns `OperationDetail`.
410
+
411
+ `OperationPageItem` / `OperationDetail` fields: `id` (number), `operationId`
412
+ (string — the idempotency key), `status` (string), `terminal` (boolean),
413
+ `retryable` (boolean), `attemptCount` (number), `businessNo` (string?),
414
+ `contractNo` (string?), `sealId` (number?), `reconciliationStatus` (string?),
415
+ `nextRetryAt` (string?), `requestedAt` (string?), `respondedAt` (string?),
416
+ `createTime` (string). Time fields are ISO-8601. These views never expose
417
+ provider raw payloads, certificates, storage keys, or contract originals.
418
+
419
+ `createTimeStart` / `createTimeEnd` are caller-supplied datetime strings parsed
420
+ by the backend as `yyyy-MM-dd HH:mm:ss`; the SDK passes them through verbatim.
421
+
422
+ ## TSA Readonly Views
423
+
424
+ Since v1.8.0 the SDK exposes the compliance gateway S3 reads: two timestamp
425
+ authority (TSA) readonly views.
426
+
427
+ ```ts
428
+ client.compliance.listTsaProviders(signal?): Promise<TsaProvider[]>;
429
+ client.compliance.getTsaStats(signal?): Promise<TsaStats>;
430
+ ```
431
+
432
+ Both are authenticated GET reads — they follow the same read semantics as
433
+ `getReport` / `getCapabilities`: one safe `401` refresh-and-replay retry.
434
+
435
+ `listTsaProviders` (`GET /compliance/timestamps/providers`) returns one
436
+ `TsaProvider` entry per configured TSA provider.
437
+
438
+ ```ts
439
+ const providers = await client.compliance.listTsaProviders();
440
+ for (const p of providers) {
441
+ console.log(p.name, p.environment, p.available);
442
+ }
443
+ ```
444
+
445
+ `TsaProvider` fields: `name` (string), `environment` (string — for example
446
+ `production` / `sandbox`), `available` (boolean). It is a readonly view — it
447
+ never exposes provider endpoints, credentials, certificates, or other internal
448
+ integration material.
449
+
450
+ `getTsaStats` (`GET /compliance/timestamps/stats`) returns a readonly
451
+ aggregation: the total timestamp count plus a per-verification-status count map.
452
+
453
+ ```ts
454
+ const stats = await client.compliance.getTsaStats();
455
+ console.log(stats.total);
456
+ console.log(stats.byVerificationStatus.VERIFIED ?? 0);
457
+ ```
458
+
459
+ `TsaStats` fields: `total` (number), `byVerificationStatus`
460
+ (`Record<string, number>` — keys are verification-status enum names such as
461
+ `VERIFIED` / `PENDING` / `FAILED`, values are counts). The map may be empty
462
+ when no timestamps exist.
463
+
464
+ ## Envelope Completion
465
+
466
+ Since v1.9.0 the SDK exposes the compliance gateway S4 envelope-completion
467
+ surface: two readonly views and one write.
468
+
469
+ ```ts
470
+ client.compliance.listEnvelopeContracts(envelopeId, signal?): Promise<EnvelopeContractItem[]>;
471
+ client.compliance.listEnvelopeProviderRequests(envelopeId, signal?): Promise<OperationPageItem[]>;
472
+ client.compliance.voidEnvelope(envelopeId, req, options?): Promise<boolean>;
473
+ ```
474
+
475
+ `listEnvelopeContracts` (`GET /compliance/signing-envelopes/{id}/contracts`)
476
+ and `listEnvelopeProviderRequests`
477
+ (`GET /compliance/signing-envelopes/{id}/provider-requests`) are authenticated
478
+ GET reads — they follow the same read semantics as `getReport` /
479
+ `getCapabilities`: one safe `401` refresh-and-replay retry. Both return a plain
480
+ array (not a `PageResult`).
481
+
482
+ ```ts
483
+ const contracts = await client.compliance.listEnvelopeContracts(envelopeId);
484
+ for (const c of contracts) {
485
+ console.log(c.contractNo, c.title, c.status, c.contentHash);
486
+ }
487
+
488
+ const providerRequests =
489
+ await client.compliance.listEnvelopeProviderRequests(envelopeId);
490
+ for (const op of providerRequests) {
491
+ console.log(op.operationId, op.status, op.terminal, op.retryable);
492
+ }
493
+ ```
494
+
495
+ `EnvelopeContractItem` fields: `id` (number), `envelopeId` (number),
496
+ `contractNo` (string), `title` (string), `mimeType` (string), `size` (number),
497
+ `hashAlgorithm` (string), `contentHash` (string), `signedContentHash`
498
+ (string?), `status` (string), `createTime` (string — ISO-8601). It is a
499
+ SDK-safe view — it never exposes contract originals, storage keys, or provider
500
+ raw payloads.
501
+
502
+ `listEnvelopeProviderRequests` **reuses** the operation-projection type
503
+ `OperationPageItem` (see *Capabilities And Operation Projection*); it describes
504
+ the progress of each provider request, orthogonal to the envelope's domain
505
+ status.
506
+
507
+ `voidEnvelope` (`POST /compliance/signing-envelopes/{id}/void`) is a **write**.
508
+ It follows the compliance write rules — it accepts the `Idempotency-Key`
509
+ header, does not auto-retry on 5xx / timeouts, and does not refresh/replay on
510
+ `401`. The void reason is required and is sent in the JSON body:
511
+
512
+ ```ts
513
+ const voided = await client.compliance.voidEnvelope(
514
+ envelopeId,
515
+ { reason: 'signed in error' },
516
+ { idempotencyKey: voidKey },
517
+ );
518
+ ```
519
+
520
+ `VoidEnvelopeRequest` is `{ reason: string }`. Persist the idempotency key on
521
+ the caller side and reuse it when resuming the same void action.
522
+
523
+ Envelope completion actions beyond this S4 subset — send, remind, authorize,
524
+ download, and token — are deferred backend-side and are not exposed as SDK
525
+ methods in this release.
526
+
527
+ ## Contract Templates
528
+
529
+ Since v1.10.0 the SDK exposes the compliance gateway S5 contract-template
530
+ surface: a `DRAFT` → `PUBLISHED` → `ARCHIVED` lifecycle with PDF upload, field
531
+ overlay, and immutable version snapshots.
532
+
533
+ ```ts
534
+ client.compliance.createContractTemplate(req, options?): Promise<ContractTemplateResp>;
535
+ client.compliance.updateContractTemplate(id, req, options?): Promise<ContractTemplateResp>;
536
+ client.compliance.deleteContractTemplate(id, options?): Promise<void>;
537
+ client.compliance.getContractTemplate(id, signal?): Promise<ContractTemplateResp>;
538
+ client.compliance.listContractTemplates(req?, signal?): Promise<PageResult<ContractTemplatePageItem>>;
539
+ client.compliance.uploadContractTemplatePdf(id, req, options?): Promise<ContractTemplateResp>;
540
+ client.compliance.publishContractTemplate(id, options?): Promise<ContractTemplateResp>;
541
+ client.compliance.archiveContractTemplate(id, options?): Promise<ContractTemplateResp>;
542
+ client.compliance.listContractTemplateVersions(id, signal?): Promise<ContractTemplateVersion[]>;
543
+ ```
544
+
545
+ Lifecycle:
546
+
547
+ ```ts
548
+ // 1) Create in DRAFT.
549
+ const tpl = await client.compliance.createContractTemplate(
550
+ { name: 'Mutual NDA', description: 'standard NDA' },
551
+ { idempotencyKey: createKey },
552
+ );
553
+
554
+ // 2) Upload PDF body (base64-encoded). pdfHash / pdfPageCount come back on the
555
+ // returned ContractTemplateResp.
556
+ const withPdf = await client.compliance.uploadContractTemplatePdf(
557
+ tpl.id,
558
+ { pdfBase64: readPdfBase64() },
559
+ { idempotencyKey: uploadKey },
560
+ );
561
+
562
+ // 3) Edit the field overlay (signatures / seals / text / date / check). Only
563
+ // allowed while the template is still DRAFT.
564
+ await client.compliance.updateContractTemplate(
565
+ tpl.id,
566
+ {
567
+ fields: [
568
+ {
569
+ key: 'sig-partyA',
570
+ type: 'signature',
571
+ label: 'Party A signature',
572
+ page: 1,
573
+ x: 100,
574
+ y: 200,
575
+ width: 80,
576
+ height: 30,
577
+ assignedRole: 'partyA',
578
+ order: 0,
579
+ required: true,
580
+ },
581
+ ],
582
+ },
583
+ { idempotencyKey: updateKey },
584
+ );
585
+
586
+ // 4) Publish — DRAFT → PUBLISHED. currentVersion increments and the fields +
587
+ // pdfHash are frozen into the version table.
588
+ const published = await client.compliance.publishContractTemplate(tpl.id, {
589
+ idempotencyKey: publishKey,
590
+ });
591
+
592
+ // 5) Optionally archive a published template — PUBLISHED → ARCHIVED. Archived
593
+ // templates are read-only.
594
+ await client.compliance.archiveContractTemplate(tpl.id, {
595
+ idempotencyKey: archiveKey,
596
+ });
597
+ ```
598
+
599
+ `createContractTemplate`, `updateContractTemplate`, `deleteContractTemplate`,
600
+ `uploadContractTemplatePdf`, `publishContractTemplate`, and
601
+ `archiveContractTemplate` are **writes**. They follow the compliance write
602
+ rules — they accept the `Idempotency-Key` header, do not auto-retry on 5xx /
603
+ timeouts, and do not refresh/replay on `401`. Persist the idempotency key on
604
+ the caller side and reuse it when resuming the same action (especially
605
+ `uploadContractTemplatePdf`, which costs bandwidth to retry).
606
+
607
+ `updateContractTemplate` and `deleteContractTemplate` are **DRAFT-only**. The
608
+ backend refuses both on `PUBLISHED` / `ARCHIVED` templates — for a published
609
+ template, switch to `archiveContractTemplate` instead of deleting it.
610
+
611
+ `uploadContractTemplatePdf` takes `{ pdfBase64 }` in the request body. The SDK
612
+ does not parse the PDF, validate geometry, or compute the hash on the
613
+ client — those happen on the backend. `pdfHash` and `pdfPageCount` come back on
614
+ the returned `ContractTemplateResp`.
615
+
616
+ `getContractTemplate`, `listContractTemplates`, and
617
+ `listContractTemplateVersions` are authenticated GET reads — they follow the
618
+ same read semantics as `getReport` / `getCapabilities`: one safe `401`
619
+ refresh-and-replay retry.
620
+
621
+ `listContractTemplates` returns a `PageResult<ContractTemplatePageItem>`. The
622
+ list-item view deliberately omits `fields` to avoid large-object N+1 on the
623
+ list endpoint — the field overlay is only present on the detail
624
+ (`ContractTemplateResp`) and on each version snapshot
625
+ (`ContractTemplateVersion`).
626
+
627
+ `listContractTemplateVersions` returns a plain array (not a `PageResult`).
628
+ Every `publishContractTemplate` call appends one immutable
629
+ `ContractTemplateVersion` — capturing the template's `name`, `pdfHash`,
630
+ `fields`, and `statusAtSnapshot` at publish time — and is the offline-review
631
+ ground truth for the version.
632
+
633
+ The 9 methods do **not** require step-up. They require the new
634
+ `ScopeComplianceContractTemplateRead` (reads) or
635
+ `ScopeComplianceContractTemplateWrite` (writes) scope.
636
+
234
637
  ## Error Classification
235
638
 
236
639
  Compliance business errors are returned as numeric Java error codes in the
@@ -252,6 +655,16 @@ switch (info.key) {
252
655
  `CompliancePollError` is used by polling helpers for terminal failure, timeout,
253
656
  abort, and unknown states.
254
657
 
658
+ Since v1.5.0, `complianceErrorToRetryAdvice(info)` projects a `ComplianceErrorInfo`
659
+ into the cross-domain `RetryAdvice` model (`retryable` / `retryAfter` /
660
+ `sameIdempotencyKeyRequired` / `manualActionRequired` / `reason` / messages /
661
+ `supportCode`). It is an additive, read-only projection — it does not modify or
662
+ replace `ComplianceErrorInfo`; `classifyComplianceError` is unchanged. The
663
+ `reason` field is a normalized mapping of the existing error-code registries, not
664
+ a new code set. Terminal errors advise a fresh idempotency key
665
+ (`sameIdempotencyKeyRequired: false`); step-up errors advise re-authenticating
666
+ and retrying with the same key.
667
+
255
668
  ## Method Status
256
669
 
257
670
  Each `client.compliance.*` method has one of four maturity grades. Treat this
@@ -261,9 +674,9 @@ for them.
261
674
 
262
675
  | Status | Methods | Meaning |
263
676
  | --- | --- | --- |
264
- | `production-ready` | `createEvidenceAsset`, `getEvidenceAsset`, `verifyEvidencePublic`, `issueTimestamp`, `issueTimestampForAsset`, `getTimestamp`, `verifyTimestamp`, `waitForTimestampVerified`, `buildEvidencePackage`, `createReport`, `getReport`, `downloadReport`, `createSigningEnvelope`, `getSigningEnvelope`, `syncSigningEnvelopeStatus`, `submitSealApproval`, `rejectSealApproval`, `cancelSealApproval`, `listPendingSealApprovals`, `getSealApproval`, `getProviderRequest`, `waitForProviderRequestTerminal`, `classifyError` | Backend endpoint, scope, DTO contract, SDK tests and docs are all closed. Safe to call in production. |
677
+ | `production-ready` | `createEvidenceAsset`, `getEvidenceAsset`, `verifyEvidencePublic`, `listEvidenceAssets`, `listEvidencePackages`, `issueTimestamp`, `issueTimestampForAsset`, `getTimestamp`, `verifyTimestamp`, `waitForTimestampVerified`, `listTimestamps`, `listTsaProviders`, `getTsaStats`, `buildEvidencePackage`, `createReport`, `getReport`, `downloadReport`, `listReports`, `createSigningEnvelope`, `getSigningEnvelope`, `syncSigningEnvelopeStatus`, `listSigningEnvelopes`, `listEnvelopeContracts`, `listEnvelopeProviderRequests`, `voidEnvelope`, `createContractTemplate`, `updateContractTemplate`, `deleteContractTemplate`, `getContractTemplate`, `listContractTemplates`, `uploadContractTemplatePdf`, `publishContractTemplate`, `archiveContractTemplate`, `listContractTemplateVersions`, `submitSealApproval`, `rejectSealApproval`, `cancelSealApproval`, `listPendingSealApprovals`, `getSealApproval`, `listSealApprovals`, `listSealUses`, `getProviderRequest`, `waitForProviderRequestTerminal`, `getCapabilities`, `getFeatureGate`, `listOperations`, `getOperation`, `classifyError` | Backend endpoint, scope, DTO contract, SDK tests and docs are all closed. Safe to call in production. |
265
678
  | `gated` | `publishReport`, `signEnvelope`, `createH5SigningUrl`, `approveSealApproval` | SDK exposes the method, but the backend fails-closed (`COMPLIANCE_STEP_UP_REQUIRED` / `ENVELOPE_GATE_CLOSED`) until step-up and the W3 gate chain are ready. The SDK does not retry and does not fake success — surface the typed error as "feature not yet open". |
266
- | `draft contract` | operation views, gate-status views, binary download helpers | Type drafts only — not exposed as callable capability in this release. |
679
+ | `draft contract` | binary download helpers | Type drafts only — not exposed as callable capability in this release. |
267
680
  | `internal-only` | distribution billing (`reserve` / `commit` / `cancel` / `reconcile` / `refund`), provider raw payloads, provider callbacks, CFCA controlled materials | Server-side S2S only. Never part of the SDK call surface; no SDK method exists for these. |
268
681
 
269
682
  `submitSealApproval` is `production-ready`: the backend enforces
@@ -271,6 +684,43 @@ for them.
271
684
  with the same key returns the original approval id instead of creating a
272
685
  duplicate. Persist the idempotency key on the caller side.
273
686
 
687
+ `getCapabilities`, `getFeatureGate`, `listOperations`, and `getOperation` are
688
+ `production-ready` against the compliance gateway S2 (`G2`) contract — endpoint,
689
+ DTO, SDK tests, and docs are closed. They are read-only GET projections and do
690
+ not themselves carry step-up or gate state; `getCapabilities` *reports* whether
691
+ the gated actions are currently executable.
692
+
693
+ `listTsaProviders` and `getTsaStats` are `production-ready` against the
694
+ compliance gateway S3 (`G3`) contract — endpoint, DTO, SDK tests, and docs are
695
+ closed. They are read-only GET projections of timestamp authority state and
696
+ aggregate counts; they carry no step-up or gate state.
697
+
698
+ `listEnvelopeContracts`, `listEnvelopeProviderRequests`, and `voidEnvelope` are
699
+ `production-ready` against the compliance gateway S4 (`G4`) contract — endpoint,
700
+ DTO, SDK tests, and docs are closed. The two `list*` methods are read-only GET
701
+ projections; `voidEnvelope` is a write that accepts `Idempotency-Key`, does not
702
+ auto-retry, and does not refresh/replay on `401`. Send / remind / authorize /
703
+ download / token actions are deferred backend-side and have no SDK method.
704
+
705
+ The 9 contract-template methods — `createContractTemplate`,
706
+ `updateContractTemplate`, `deleteContractTemplate`, `getContractTemplate`,
707
+ `listContractTemplates`, `uploadContractTemplatePdf`,
708
+ `publishContractTemplate`, `archiveContractTemplate`,
709
+ `listContractTemplateVersions` — are `production-ready` against the compliance
710
+ gateway S5 (`G5`) contract: endpoint, DTO, SDK tests, and docs are closed. Reads
711
+ are GET (one safe `401` refresh-and-replay); writes accept `Idempotency-Key`,
712
+ do not auto-retry, and do not refresh/replay on `401`. None of them require
713
+ step-up. `updateContractTemplate` and `deleteContractTemplate` are
714
+ DRAFT-only — the backend refuses both on `PUBLISHED` / `ARCHIVED` templates.
715
+
716
+ `listSealUses` is `production-ready` against the compliance gateway S6 (`G6`)
717
+ contract — endpoint, DTO, SDK tests, and docs are closed. It is a read-only
718
+ GET projection (one safe `401` refresh-and-replay) and reuses the existing
719
+ `ScopeComplianceContractSigningRead` scope; no new scope is introduced. The
720
+ broader seal authorization layer and seal CRUD surface (gap-register U-3 /
721
+ U-11) remain backend-deferred behind the CFCA private jar and the W3 gate;
722
+ they are intentionally **not** exposed as SDK methods in this release.
723
+
274
724
  ## Safety Boundary
275
725
 
276
726
  Do not place any of the following in SDK code, tests, examples, docs, git
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acosmi/sdk-ts",
3
- "version": "1.4.2",
3
+ "version": "1.5.0",
4
4
  "description": "Acosmi TypeScript SDK:模型网关、Agent Run Gateway 与 Compliance(电子证据、时间章、报告、签署 envelope)统一客户端,支持浏览器 / Node ≥18 / Deno / Bun。",
5
5
  "type": "module",
6
6
  "main": "./dist/node/index.cjs",