@acosmi/sdk-ts 1.4.2 → 1.5.1

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.5.0; originally planned as v1.10.0 — see
94
+ CHANGELOG §"S5:合同模板") are split by direction and do not 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.5.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,403 @@ if (view.status === 'SUCCESS') {
231
242
  }
232
243
  ```
233
244
 
245
+ ## Paginated Lists
246
+
247
+ Since v1.5.0 (originally planned as v1.6.0 — see CHANGELOG §"S1:6 个分页列表")
248
+ the SDK exposes paginated list reads against the backend
249
+ compliance gateway (`GET .../page`). Each returns a yudao `PageResult<T>`
250
+ (`{ total, list }` — the single SDK-wide pagination result shape, an alias of
251
+ `YudaoPageResult<T>`):
252
+
253
+ ```ts
254
+ import type { PageResult, EvidenceAssetPageItem } from '@acosmi/sdk-ts';
255
+
256
+ client.compliance.listEvidenceAssets(req?, signal?): Promise<PageResult<EvidenceAssetPageItem>>;
257
+ client.compliance.listTimestamps(req?, signal?): Promise<PageResult<TimestampPageItem>>;
258
+ client.compliance.listEvidencePackages(req?, signal?): Promise<PageResult<EvidencePackagePageItem>>;
259
+ client.compliance.listReports(req?, signal?): Promise<PageResult<ReportPageItem>>;
260
+ client.compliance.listSigningEnvelopes(req?, signal?): Promise<PageResult<SigningEnvelopePageItem>>;
261
+ client.compliance.listSealApprovals(req?, signal?): Promise<PageResult<SealApprovalPageItem>>;
262
+ client.compliance.listSealUses(req?, signal?): Promise<PageResult<SealUsePageItem>>;
263
+ ```
264
+
265
+ The request argument is optional. It extends the shared `PageRequest`
266
+ (`pageNo`, `pageSize`, `sortBy`, `sortDirection` — all optional; omitted values
267
+ let the backend pick defaults) plus per-method filters:
268
+
269
+ | Method | Endpoint | Filters (all optional) |
270
+ | --- | --- | --- |
271
+ | `listEvidenceAssets` | `GET /compliance/evidence/assets/page` | `assetType`, `status`, `createTimeStart`, `createTimeEnd` |
272
+ | `listTimestamps` | `GET /compliance/timestamps/page` | `provider`, `verificationStatus`, `createTimeStart`, `createTimeEnd` |
273
+ | `listEvidencePackages` | `GET /compliance/evidence/packages/page` | `status`, `createTimeStart`, `createTimeEnd` |
274
+ | `listReports` | `GET /compliance/reports/page` | `status`, `createTimeStart`, `createTimeEnd` |
275
+ | `listSigningEnvelopes` | `GET /compliance/signing-envelopes/page` | `status`, `createTimeStart`, `createTimeEnd` |
276
+ | `listSealApprovals` | `GET /compliance/seal-approvals/page` | `status`, `createTimeStart`, `createTimeEnd` |
277
+ | `listSealUses` | `GET /compliance/seal-uses/page` | `sealId`, `envelopeId`, `usageStatus`, `createTimeStart`, `createTimeEnd` |
278
+
279
+ `createTimeStart` / `createTimeEnd` are caller-supplied datetime **strings**. The
280
+ backend parses them as `yyyy-MM-dd HH:mm:ss` (for example
281
+ `'2026-05-01 00:00:00'`). The SDK passes them through verbatim — it does not
282
+ validate the format or convert time zones.
283
+
284
+ ```ts
285
+ const page = await client.compliance.listSealApprovals({
286
+ pageNo: 1,
287
+ pageSize: 20,
288
+ status: 'PENDING',
289
+ createTimeStart: '2026-05-01 00:00:00',
290
+ createTimeEnd: '2026-05-22 23:59:59',
291
+ });
292
+
293
+ console.log(page.total, page.list.length);
294
+ ```
295
+
296
+ These are authenticated GET reads, so they follow the same read semantics as
297
+ `getEvidenceAsset` / `getReport`: one safe `401` refresh-and-replay retry.
298
+
299
+ `listSealApprovals` is distinct from `listPendingSealApprovals` — the latter
300
+ returns only pending approvals as a plain array; `listSealApprovals` is paginated
301
+ and supports status / time filtering.
302
+
303
+ The `*PageItem` types (`EvidenceAssetPageItem`, `TimestampPageItem`,
304
+ `EvidencePackagePageItem`, `ReportPageItem`, `SigningEnvelopePageItem`,
305
+ `SealApprovalPageItem`, `SealUsePageItem`) are the SDK-safe subset of the
306
+ corresponding detail view plus a `createTime` (ISO-8601) field. They never
307
+ expose provider raw payloads, certificates, storage keys, or contract originals.
308
+
309
+ `listSealUses` (compliance gateway S6) returns one row per **seal use** — the
310
+ real `provider`-side seal application that fires after envelope / contract /
311
+ seal / approval are linked. It is orthogonal to the envelope domain status and
312
+ to the seal-approval workflow:
313
+
314
+ - `listSigningEnvelopes` → high-level envelope domain state.
315
+ - `listSealApprovals` → the approval workflow on an envelope (`PENDING` →
316
+ `APPROVED` / `REJECTED` / `CANCELED`).
317
+ - `listSealUses` → the actual seal-application execution
318
+ (`invokedAt` → `consumedAt`, with `failureReason` on terminal failure).
319
+
320
+ `SealUsePageItem` fields: `id` (number), `envelopeId` (number), `contractId`
321
+ (number), `sealId` (number), `usageStatus` (string), `signLocationType`
322
+ (string?), `invokedAt` (string?), `consumedAt` (string?), `failureReason`
323
+ (string?), `createTime` (string — ISO-8601).
324
+
325
+ `listSealUses` reuses the existing read scope
326
+ `ScopeComplianceContractSigningRead` (`compliance:contract_signing:read`); it
327
+ does not introduce a new scope. The seal authorization surface and the full
328
+ seal CRUD (gap-register U-3 / U-11) remain backend-deferred behind the CFCA
329
+ private jar and the W3 gate, and are not exposed as SDK methods in this
330
+ release.
331
+
332
+ ## Capabilities And Operation Projection
333
+
334
+ Since v1.5.0 (originally planned as v1.7.0 — see CHANGELOG §"S2:capabilities +
335
+ operations 投影") the SDK exposes the compliance gateway S2 reads: a capability gate
336
+ query and an operation-projection view.
337
+
338
+ ```ts
339
+ client.compliance.getCapabilities(signal?): Promise<ComplianceCapability[]>;
340
+ client.compliance.getFeatureGate(action, signal?): Promise<ComplianceCapability | undefined>;
341
+ client.compliance.listOperations(req?, signal?): Promise<PageResult<OperationPageItem>>;
342
+ client.compliance.getOperation(id, signal?): Promise<OperationDetail>;
343
+ ```
344
+
345
+ All four are authenticated GET reads — they follow the same read semantics as
346
+ `getReport` / `getEvidenceAsset`: one safe `401` refresh-and-replay retry.
347
+
348
+ ### Capabilities
349
+
350
+ `getCapabilities` returns one `ComplianceCapability` entry per high-risk /
351
+ billed action: `signEnvelope`, `createH5SigningUrl`, `publishReport`,
352
+ `approveSealApproval`, `executeSealUse`, `createSeal`.
353
+
354
+ ```ts
355
+ const caps = await client.compliance.getCapabilities();
356
+ for (const cap of caps) {
357
+ console.log(cap.action, cap.executable, cap.state, cap.requiredScopes);
358
+ }
359
+ ```
360
+
361
+ `ComplianceCapability` fields: `action` (string), `executable` (boolean),
362
+ `state` (`executable` / `scope_missing` / `not_provisioned` /
363
+ `step_up_required` / `gate_closed` / `unknown` — reuses the cross-domain
364
+ `FeatureGateState` open union), `requiredScopes` (string[]), `requiredStepUp`
365
+ (boolean), `reason` (string).
366
+
367
+ Query the capability **before** invoking a high-risk action and gate the UI on
368
+ it. When the capability cannot be fetched, fail-closed — treat the action as
369
+ `executable: false`.
370
+
371
+ `getFeatureGate` is a convenience that fetches `getCapabilities` and returns the
372
+ entry whose `action` matches (or `undefined` when none match). **Each call makes
373
+ one network request.** To gate several actions, call `getCapabilities` once and
374
+ look them up locally instead of calling `getFeatureGate` repeatedly.
375
+
376
+ ```ts
377
+ const gate = await client.compliance.getFeatureGate('publishReport');
378
+ if (!gate || !gate.executable) {
379
+ if (gate?.state === 'step_up_required') {
380
+ await promptUserToReauthenticate();
381
+ }
382
+ return; // fail-closed
383
+ }
384
+ ```
385
+
386
+ ### Operation Projection
387
+
388
+ The operation projection describes the progress of a single operation — it is
389
+ orthogonal to a fulfillment object's domain status.
390
+
391
+ ```ts
392
+ const page = await client.compliance.listOperations({
393
+ pageNo: 1,
394
+ pageSize: 20,
395
+ status: 'failed',
396
+ createTimeStart: '2026-05-01 00:00:00',
397
+ createTimeEnd: '2026-05-22 23:59:59',
398
+ });
399
+
400
+ for (const op of page.list) {
401
+ console.log(op.id, op.operationId, op.status, op.terminal, op.retryable);
402
+ }
403
+
404
+ const detail = await client.compliance.getOperation(page.list[0].id);
405
+ ```
406
+
407
+ `listOperations` (`GET /compliance/operations/page`) returns a yudao
408
+ `PageResult<OperationPageItem>`. Its request extends the shared `PageRequest`
409
+ plus the optional `status` / `createTimeStart` / `createTimeEnd` filters.
410
+ `getOperation` (`GET /compliance/operations/{id}`) takes the numeric **row id**
411
+ (not the `operationId` idempotency key) and returns `OperationDetail`.
412
+
413
+ `OperationPageItem` / `OperationDetail` fields: `id` (number), `operationId`
414
+ (string — the idempotency key), `status` (string), `terminal` (boolean),
415
+ `retryable` (boolean), `attemptCount` (number), `businessNo` (string?),
416
+ `contractNo` (string?), `sealId` (number?), `reconciliationStatus` (string?),
417
+ `nextRetryAt` (string?), `requestedAt` (string?), `respondedAt` (string?),
418
+ `createTime` (string). Time fields are ISO-8601. These views never expose
419
+ provider raw payloads, certificates, storage keys, or contract originals.
420
+
421
+ `createTimeStart` / `createTimeEnd` are caller-supplied datetime strings parsed
422
+ by the backend as `yyyy-MM-dd HH:mm:ss`; the SDK passes them through verbatim.
423
+
424
+ ## TSA Readonly Views
425
+
426
+ Since v1.5.0 (originally planned as v1.8.0 — see CHANGELOG §"S3:TSA readonly
427
+ 视图") the SDK exposes the compliance gateway S3 reads: two timestamp
428
+ authority (TSA) readonly views.
429
+
430
+ ```ts
431
+ client.compliance.listTsaProviders(signal?): Promise<TsaProvider[]>;
432
+ client.compliance.getTsaStats(signal?): Promise<TsaStats>;
433
+ ```
434
+
435
+ Both are authenticated GET reads — they follow the same read semantics as
436
+ `getReport` / `getCapabilities`: one safe `401` refresh-and-replay retry.
437
+
438
+ `listTsaProviders` (`GET /compliance/timestamps/providers`) returns one
439
+ `TsaProvider` entry per configured TSA provider.
440
+
441
+ ```ts
442
+ const providers = await client.compliance.listTsaProviders();
443
+ for (const p of providers) {
444
+ console.log(p.name, p.environment, p.available);
445
+ }
446
+ ```
447
+
448
+ `TsaProvider` fields: `name` (string), `environment` (string — for example
449
+ `production` / `sandbox`), `available` (boolean). It is a readonly view — it
450
+ never exposes provider endpoints, credentials, certificates, or other internal
451
+ integration material.
452
+
453
+ `getTsaStats` (`GET /compliance/timestamps/stats`) returns a readonly
454
+ aggregation: the total timestamp count plus a per-verification-status count map.
455
+
456
+ ```ts
457
+ const stats = await client.compliance.getTsaStats();
458
+ console.log(stats.total);
459
+ console.log(stats.byVerificationStatus.VERIFIED ?? 0);
460
+ ```
461
+
462
+ `TsaStats` fields: `total` (number), `byVerificationStatus`
463
+ (`Record<string, number>` — keys are verification-status enum names such as
464
+ `VERIFIED` / `PENDING` / `FAILED`, values are counts). The map may be empty
465
+ when no timestamps exist.
466
+
467
+ ## Envelope Completion
468
+
469
+ Since v1.5.0 (originally planned as v1.9.0 — see CHANGELOG §"S4:envelope 收尾
470
+ + void") the SDK exposes the compliance gateway S4 envelope-completion
471
+ surface: two readonly views and one write.
472
+
473
+ ```ts
474
+ client.compliance.listEnvelopeContracts(envelopeId, signal?): Promise<EnvelopeContractItem[]>;
475
+ client.compliance.listEnvelopeProviderRequests(envelopeId, signal?): Promise<OperationPageItem[]>;
476
+ client.compliance.voidEnvelope(envelopeId, req, options?): Promise<boolean>;
477
+ ```
478
+
479
+ `listEnvelopeContracts` (`GET /compliance/signing-envelopes/{id}/contracts`)
480
+ and `listEnvelopeProviderRequests`
481
+ (`GET /compliance/signing-envelopes/{id}/provider-requests`) are authenticated
482
+ GET reads — they follow the same read semantics as `getReport` /
483
+ `getCapabilities`: one safe `401` refresh-and-replay retry. Both return a plain
484
+ array (not a `PageResult`).
485
+
486
+ ```ts
487
+ const contracts = await client.compliance.listEnvelopeContracts(envelopeId);
488
+ for (const c of contracts) {
489
+ console.log(c.contractNo, c.title, c.status, c.contentHash);
490
+ }
491
+
492
+ const providerRequests =
493
+ await client.compliance.listEnvelopeProviderRequests(envelopeId);
494
+ for (const op of providerRequests) {
495
+ console.log(op.operationId, op.status, op.terminal, op.retryable);
496
+ }
497
+ ```
498
+
499
+ `EnvelopeContractItem` fields: `id` (number), `envelopeId` (number),
500
+ `contractNo` (string), `title` (string), `mimeType` (string), `size` (number),
501
+ `hashAlgorithm` (string), `contentHash` (string), `signedContentHash`
502
+ (string?), `status` (string), `createTime` (string — ISO-8601). It is a
503
+ SDK-safe view — it never exposes contract originals, storage keys, or provider
504
+ raw payloads.
505
+
506
+ `listEnvelopeProviderRequests` **reuses** the operation-projection type
507
+ `OperationPageItem` (see *Capabilities And Operation Projection*); it describes
508
+ the progress of each provider request, orthogonal to the envelope's domain
509
+ status.
510
+
511
+ `voidEnvelope` (`POST /compliance/signing-envelopes/{id}/void`) is a **write**.
512
+ It follows the compliance write rules — it accepts the `Idempotency-Key`
513
+ header, does not auto-retry on 5xx / timeouts, and does not refresh/replay on
514
+ `401`. The void reason is required and is sent in the JSON body:
515
+
516
+ ```ts
517
+ const voided = await client.compliance.voidEnvelope(
518
+ envelopeId,
519
+ { reason: 'signed in error' },
520
+ { idempotencyKey: voidKey },
521
+ );
522
+ ```
523
+
524
+ `VoidEnvelopeRequest` is `{ reason: string }`. Persist the idempotency key on
525
+ the caller side and reuse it when resuming the same void action.
526
+
527
+ Envelope completion actions beyond this S4 subset — send, remind, authorize,
528
+ download, and token — are deferred backend-side and are not exposed as SDK
529
+ methods in this release.
530
+
531
+ ## Contract Templates
532
+
533
+ Since v1.5.0 (originally planned as v1.10.0 — see CHANGELOG §"S5:合同模板")
534
+ the SDK exposes the compliance gateway S5 contract-template
535
+ surface: a `DRAFT` → `PUBLISHED` → `ARCHIVED` lifecycle with PDF upload, field
536
+ overlay, and immutable version snapshots.
537
+
538
+ ```ts
539
+ client.compliance.createContractTemplate(req, options?): Promise<ContractTemplateResp>;
540
+ client.compliance.updateContractTemplate(id, req, options?): Promise<ContractTemplateResp>;
541
+ client.compliance.deleteContractTemplate(id, options?): Promise<void>;
542
+ client.compliance.getContractTemplate(id, signal?): Promise<ContractTemplateResp>;
543
+ client.compliance.listContractTemplates(req?, signal?): Promise<PageResult<ContractTemplatePageItem>>;
544
+ client.compliance.uploadContractTemplatePdf(id, req, options?): Promise<ContractTemplateResp>;
545
+ client.compliance.publishContractTemplate(id, options?): Promise<ContractTemplateResp>;
546
+ client.compliance.archiveContractTemplate(id, options?): Promise<ContractTemplateResp>;
547
+ client.compliance.listContractTemplateVersions(id, signal?): Promise<ContractTemplateVersion[]>;
548
+ ```
549
+
550
+ Lifecycle:
551
+
552
+ ```ts
553
+ // 1) Create in DRAFT.
554
+ const tpl = await client.compliance.createContractTemplate(
555
+ { name: 'Mutual NDA', description: 'standard NDA' },
556
+ { idempotencyKey: createKey },
557
+ );
558
+
559
+ // 2) Upload PDF body (base64-encoded). pdfHash / pdfPageCount come back on the
560
+ // returned ContractTemplateResp.
561
+ const withPdf = await client.compliance.uploadContractTemplatePdf(
562
+ tpl.id,
563
+ { pdfBase64: readPdfBase64() },
564
+ { idempotencyKey: uploadKey },
565
+ );
566
+
567
+ // 3) Edit the field overlay (signatures / seals / text / date / check). Only
568
+ // allowed while the template is still DRAFT.
569
+ await client.compliance.updateContractTemplate(
570
+ tpl.id,
571
+ {
572
+ fields: [
573
+ {
574
+ key: 'sig-partyA',
575
+ type: 'signature',
576
+ label: 'Party A signature',
577
+ page: 1,
578
+ x: 100,
579
+ y: 200,
580
+ width: 80,
581
+ height: 30,
582
+ assignedRole: 'partyA',
583
+ order: 0,
584
+ required: true,
585
+ },
586
+ ],
587
+ },
588
+ { idempotencyKey: updateKey },
589
+ );
590
+
591
+ // 4) Publish — DRAFT → PUBLISHED. currentVersion increments and the fields +
592
+ // pdfHash are frozen into the version table.
593
+ const published = await client.compliance.publishContractTemplate(tpl.id, {
594
+ idempotencyKey: publishKey,
595
+ });
596
+
597
+ // 5) Optionally archive a published template — PUBLISHED → ARCHIVED. Archived
598
+ // templates are read-only.
599
+ await client.compliance.archiveContractTemplate(tpl.id, {
600
+ idempotencyKey: archiveKey,
601
+ });
602
+ ```
603
+
604
+ `createContractTemplate`, `updateContractTemplate`, `deleteContractTemplate`,
605
+ `uploadContractTemplatePdf`, `publishContractTemplate`, and
606
+ `archiveContractTemplate` are **writes**. They follow the compliance write
607
+ rules — they accept the `Idempotency-Key` header, do not auto-retry on 5xx /
608
+ timeouts, and do not refresh/replay on `401`. Persist the idempotency key on
609
+ the caller side and reuse it when resuming the same action (especially
610
+ `uploadContractTemplatePdf`, which costs bandwidth to retry).
611
+
612
+ `updateContractTemplate` and `deleteContractTemplate` are **DRAFT-only**. The
613
+ backend refuses both on `PUBLISHED` / `ARCHIVED` templates — for a published
614
+ template, switch to `archiveContractTemplate` instead of deleting it.
615
+
616
+ `uploadContractTemplatePdf` takes `{ pdfBase64 }` in the request body. The SDK
617
+ does not parse the PDF, validate geometry, or compute the hash on the
618
+ client — those happen on the backend. `pdfHash` and `pdfPageCount` come back on
619
+ the returned `ContractTemplateResp`.
620
+
621
+ `getContractTemplate`, `listContractTemplates`, and
622
+ `listContractTemplateVersions` are authenticated GET reads — they follow the
623
+ same read semantics as `getReport` / `getCapabilities`: one safe `401`
624
+ refresh-and-replay retry.
625
+
626
+ `listContractTemplates` returns a `PageResult<ContractTemplatePageItem>`. The
627
+ list-item view deliberately omits `fields` to avoid large-object N+1 on the
628
+ list endpoint — the field overlay is only present on the detail
629
+ (`ContractTemplateResp`) and on each version snapshot
630
+ (`ContractTemplateVersion`).
631
+
632
+ `listContractTemplateVersions` returns a plain array (not a `PageResult`).
633
+ Every `publishContractTemplate` call appends one immutable
634
+ `ContractTemplateVersion` — capturing the template's `name`, `pdfHash`,
635
+ `fields`, and `statusAtSnapshot` at publish time — and is the offline-review
636
+ ground truth for the version.
637
+
638
+ The 9 methods do **not** require step-up. They require the new
639
+ `ScopeComplianceContractTemplateRead` (reads) or
640
+ `ScopeComplianceContractTemplateWrite` (writes) scope.
641
+
234
642
  ## Error Classification
235
643
 
236
644
  Compliance business errors are returned as numeric Java error codes in the
@@ -252,6 +660,16 @@ switch (info.key) {
252
660
  `CompliancePollError` is used by polling helpers for terminal failure, timeout,
253
661
  abort, and unknown states.
254
662
 
663
+ Since v1.5.0, `complianceErrorToRetryAdvice(info)` projects a `ComplianceErrorInfo`
664
+ into the cross-domain `RetryAdvice` model (`retryable` / `retryAfter` /
665
+ `sameIdempotencyKeyRequired` / `manualActionRequired` / `reason` / messages /
666
+ `supportCode`). It is an additive, read-only projection — it does not modify or
667
+ replace `ComplianceErrorInfo`; `classifyComplianceError` is unchanged. The
668
+ `reason` field is a normalized mapping of the existing error-code registries, not
669
+ a new code set. Terminal errors advise a fresh idempotency key
670
+ (`sameIdempotencyKeyRequired: false`); step-up errors advise re-authenticating
671
+ and retrying with the same key.
672
+
255
673
  ## Method Status
256
674
 
257
675
  Each `client.compliance.*` method has one of four maturity grades. Treat this
@@ -261,9 +679,9 @@ for them.
261
679
 
262
680
  | Status | Methods | Meaning |
263
681
  | --- | --- | --- |
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. |
682
+ | `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
683
  | `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. |
684
+ | `draft contract` | binary download helpers | Type drafts only — not exposed as callable capability in this release. |
267
685
  | `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
686
 
269
687
  `submitSealApproval` is `production-ready`: the backend enforces
@@ -271,6 +689,43 @@ for them.
271
689
  with the same key returns the original approval id instead of creating a
272
690
  duplicate. Persist the idempotency key on the caller side.
273
691
 
692
+ `getCapabilities`, `getFeatureGate`, `listOperations`, and `getOperation` are
693
+ `production-ready` against the compliance gateway S2 (`G2`) contract — endpoint,
694
+ DTO, SDK tests, and docs are closed. They are read-only GET projections and do
695
+ not themselves carry step-up or gate state; `getCapabilities` *reports* whether
696
+ the gated actions are currently executable.
697
+
698
+ `listTsaProviders` and `getTsaStats` are `production-ready` against the
699
+ compliance gateway S3 (`G3`) contract — endpoint, DTO, SDK tests, and docs are
700
+ closed. They are read-only GET projections of timestamp authority state and
701
+ aggregate counts; they carry no step-up or gate state.
702
+
703
+ `listEnvelopeContracts`, `listEnvelopeProviderRequests`, and `voidEnvelope` are
704
+ `production-ready` against the compliance gateway S4 (`G4`) contract — endpoint,
705
+ DTO, SDK tests, and docs are closed. The two `list*` methods are read-only GET
706
+ projections; `voidEnvelope` is a write that accepts `Idempotency-Key`, does not
707
+ auto-retry, and does not refresh/replay on `401`. Send / remind / authorize /
708
+ download / token actions are deferred backend-side and have no SDK method.
709
+
710
+ The 9 contract-template methods — `createContractTemplate`,
711
+ `updateContractTemplate`, `deleteContractTemplate`, `getContractTemplate`,
712
+ `listContractTemplates`, `uploadContractTemplatePdf`,
713
+ `publishContractTemplate`, `archiveContractTemplate`,
714
+ `listContractTemplateVersions` — are `production-ready` against the compliance
715
+ gateway S5 (`G5`) contract: endpoint, DTO, SDK tests, and docs are closed. Reads
716
+ are GET (one safe `401` refresh-and-replay); writes accept `Idempotency-Key`,
717
+ do not auto-retry, and do not refresh/replay on `401`. None of them require
718
+ step-up. `updateContractTemplate` and `deleteContractTemplate` are
719
+ DRAFT-only — the backend refuses both on `PUBLISHED` / `ARCHIVED` templates.
720
+
721
+ `listSealUses` is `production-ready` against the compliance gateway S6 (`G6`)
722
+ contract — endpoint, DTO, SDK tests, and docs are closed. It is a read-only
723
+ GET projection (one safe `401` refresh-and-replay) and reuses the existing
724
+ `ScopeComplianceContractSigningRead` scope; no new scope is introduced. The
725
+ broader seal authorization layer and seal CRUD surface (gap-register U-3 /
726
+ U-11) remain backend-deferred behind the CFCA private jar and the W3 gate;
727
+ they are intentionally **not** exposed as SDK methods in this release.
728
+
274
729
  ## Safety Boundary
275
730
 
276
731
  Do not place any of the following in SDK code, tests, examples, docs, git
@@ -11,8 +11,12 @@
11
11
  // 说明:
12
12
  // - 大多数场景直接用 `client.login(appName, scopes)` 即可(内部封装了下面全部步骤)。
13
13
  // 本示例演示底层 helper,适用于需要自定义授权流程 / 自管 token 的 CLI。
14
- // - authorize 仅在 Node 环境可用(需要本地 HTTP 回调 server);浏览器侧应自行实现
15
- // popup window + redirect handler。
14
+ // - authorize 仅在 Node 环境可用(需要本地 HTTP 回调 server)。
15
+ // - 浏览器侧(无 loopback server)请改用 v1.4.0+ Web OAuth 原语:
16
+ // discoverWebOAuthMetadata + registerWebOAuthClient +
17
+ // createWebAuthorizationRequest + completeWebAuthorizationRequest,
18
+ // 由调用方实现 popup / 同窗口 redirect handler,SDK 负责 PKCE / state 校验 / token 兑换。
19
+ // 浏览器 token 刷新可配 Config.browserRefreshMode / refreshProxyURL (v1.4.1+) 规避 issuer CORS 403。
16
20
 
17
21
  import {
18
22
  discover,
@@ -22,6 +22,7 @@ import {
22
22
  ScopeComplianceTimestampIssue,
23
23
  ScopeComplianceTimestampVerify,
24
24
  ScopeComplianceReportsRead,
25
+ ScopeComplianceReportsWrite,
25
26
  } from '@acosmi/sdk-ts';
26
27
 
27
28
  // 模拟持久化的 Idempotency-Key 存储;生产环境应落 DB / 本地文件 / 业务订单表。
@@ -51,7 +52,8 @@ async function main() {
51
52
  ScopeComplianceEvidenceWrite,
52
53
  ScopeComplianceTimestampIssue,
53
54
  ScopeComplianceTimestampVerify,
54
- ScopeComplianceReportsRead,
55
+ ScopeComplianceReportsRead, // getReport / downloadReport
56
+ ScopeComplianceReportsWrite, // createReport(v1.3.2 起从 read 切到独立 write scope)
55
57
  ]);
56
58
 
57
59
  // 1) 本地 sha256 (用户业务内容)
@@ -8,9 +8,12 @@
8
8
  // 5. 流式 chatStreamWithUsage 并聚合 usage / 结算事件
9
9
  //
10
10
  // 说明:
11
- // - SDK 自动按 ManagedModel 的 preferredFormat / supportedFormats 选 Anthropic
12
- // 或 OpenAI adapter,调用方无需关心。
11
+ // - SDK 自动按 ManagedModel 的 preferred_format / supported_formats(snake_case
12
+ // wire 字段)选 Anthropic 或 OpenAI adapter,调用方无需关心。详见
13
+ // src/models/adapters/index.ts:getAdapterForModel。
13
14
  // - 金额 / 余额字段是 string(避免 JS number 精度损失),不要做浮点运算。
15
+ // - ChatRequest 走 snake_case wire 字段(max_tokens 等),与上游 Go json tag 对齐;
16
+ // ManagedModel 顶层多为 camelCase(modelId / isEnabled / inputModalities)。
14
17
 
15
18
  import { Client, allScopes, FileTokenStore } from '@acosmi/sdk-ts';
16
19
 
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.1",
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",