@verentis/sdk 0.2.4 → 0.2.5

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/index.d.ts CHANGED
@@ -26,6 +26,195 @@ interface HeaderActionRegistration {
26
26
  type HeaderActionHandler = () => void | HeaderActionResult | Promise<void | HeaderActionResult>;
27
27
  declare function isHeaderAction(value: unknown): value is HeaderAction;
28
28
 
29
+ type BridgeEventType = HostToAppMessage['type'];
30
+ /** Handles a host message; the resolved value (structured-cloneable, ideally JSON) is the reply. */
31
+ type HostMessageHandler = (payload: unknown) => unknown | Promise<unknown>;
32
+ /** Channel names declared in the manifest `spec.messages`. */
33
+ declare const HOST_MESSAGE_CHANNEL_PATTERN: RegExp;
34
+ type BridgeListener = (data: HostToAppMessage) => void;
35
+ /**
36
+ * PostMessage bridge for communication between an app (iframe) and the
37
+ * workspace host. Handles the initialization handshake, token lifecycle,
38
+ * and app-to-host events (navigate, resize, dirty, etc.).
39
+ */
40
+ declare class Bridge {
41
+ private readonly expectedHostOrigin?;
42
+ private listeners;
43
+ private _initResolve;
44
+ private _initReject;
45
+ private _initTimer;
46
+ private _initPromise;
47
+ private _hostOrigin;
48
+ private _messageHandler;
49
+ private _destroyed;
50
+ private sessionId;
51
+ private actions;
52
+ private requests;
53
+ private hostMessageHandlers;
54
+ private hostMessageRequests;
55
+ private wopiRequests;
56
+ private collaborationRequests;
57
+ constructor(expectedHostOrigin?: string | undefined);
58
+ /** Post `verentis:ready` to the host to start the handshake */
59
+ sendReady(capabilities?: string[]): void;
60
+ /** Wait for the host to send `verentis:init` with context and token */
61
+ waitForInit(): Promise<{
62
+ context: AppContext;
63
+ token: TokenInfo;
64
+ }>;
65
+ /** Get the host origin (available after init) */
66
+ get hostOrigin(): string | null;
67
+ /** Send a message to the host */
68
+ postToHost(message: AppToHostMessage): void;
69
+ /**
70
+ * Navigate to another location in the workspace.
71
+ *
72
+ * @param path A workspace file path (e.g. `/reports/q1.json`) or an absolute
73
+ * http(s) URL. External URLs require the app to declare the
74
+ * `navigation:external` capability in its manifest.
75
+ * @param options Navigation options. Set `newTab: true` to open the target in
76
+ * a new browser tab instead of the current one.
77
+ */
78
+ navigate(path: string, options?: NavigateOptions): void;
79
+ /** Request iframe resize */
80
+ resize(height: number): void;
81
+ /** Update the title displayed by the host */
82
+ setTitle(title: string): void;
83
+ /** Signal unsaved changes to the host */
84
+ setDirty(isDirty: boolean): void;
85
+ /** The trusted parent selects the approved installation, document and action. */
86
+ requestWopiLaunch(): Promise<WopiLaunch>;
87
+ /** Recover only the target selected by a completed server-owned derived operation. */
88
+ requestWopiContinuation(): Promise<WopiContinuation>;
89
+ getWopiStatus(): Promise<WopiSaveStatus>;
90
+ requestWopiSave(generation: number): Promise<WopiSaveCheckpoint>;
91
+ closeWopiSession(): Promise<void>;
92
+ private requestWopi;
93
+ requestNativeCollaboration(command: NativeCollaborationCommand): Promise<unknown>;
94
+ registerAction(descriptor: HeaderAction, handler: HeaderActionHandler): HeaderActionRegistration;
95
+ private publishActions;
96
+ private invokeAction;
97
+ /**
98
+ * Handle messages the workspace sends on a channel declared in the manifest `spec.messages` — for
99
+ * example an agent asking the open app to select a record. The handler's return value is the reply;
100
+ * a thrown error is reported back as the failure. May be called before the init handshake.
101
+ */
102
+ onHostMessage(channel: string, handler: HostMessageHandler): () => void;
103
+ private receiveHostMessage;
104
+ /** Subscribe to a specific message type from the host */
105
+ on(type: BridgeEventType, listener: BridgeListener): () => void;
106
+ /** Clean up event listeners */
107
+ destroy(): void;
108
+ private handleMessage;
109
+ }
110
+
111
+ interface NativeElement {
112
+ id: string;
113
+ version: number;
114
+ versionNonce?: number;
115
+ isDeleted?: boolean;
116
+ [key: string]: unknown;
117
+ }
118
+ interface NativeFile {
119
+ id: string;
120
+ dataURL: string;
121
+ mimeType: string;
122
+ created: number;
123
+ lastRetrieved?: number;
124
+ }
125
+ interface NativeScene {
126
+ elements: NativeElement[];
127
+ files: Record<string, NativeFile>;
128
+ appState: Record<string, unknown>;
129
+ }
130
+ interface NativePointer {
131
+ x: number;
132
+ y: number;
133
+ }
134
+ interface NativeParticipant {
135
+ id: string;
136
+ name: string;
137
+ readOnly: boolean;
138
+ pointer: NativePointer | null;
139
+ /** `agent` marks an agent acting on behalf of a user (same principal, separate connection). */
140
+ kind?: 'user' | 'agent';
141
+ }
142
+ interface NativeSnapshot {
143
+ sequence: number;
144
+ savedSequence: number;
145
+ revision: string;
146
+ readOnly: boolean;
147
+ scene: NativeScene;
148
+ participants: NativeParticipant[];
149
+ }
150
+ interface NativeSaveReceipt {
151
+ generation: number;
152
+ correlation: string;
153
+ revision: string;
154
+ }
155
+ interface NativeSaveResult extends NativeSnapshot {
156
+ receipt: NativeSaveReceipt;
157
+ }
158
+ interface NativeChangeSet {
159
+ operationId: string;
160
+ changes: Array<{
161
+ id: string;
162
+ expectedVersion: number | null;
163
+ element: NativeElement | null;
164
+ }>;
165
+ files?: Record<string, NativeFile>;
166
+ appState?: Record<string, unknown>;
167
+ appStateExpectedSequence?: number;
168
+ }
169
+ type NativeCollaborationCommand = {
170
+ operation: 'join' | 'snapshot' | 'close';
171
+ } | {
172
+ operation: 'apply';
173
+ changes: NativeChangeSet;
174
+ } | {
175
+ operation: 'presence';
176
+ pointer: NativePointer | null;
177
+ } | {
178
+ operation: 'save';
179
+ generation: number;
180
+ correlation: string;
181
+ };
182
+ interface NativeCollaborationRequest {
183
+ type: 'verentis:collaboration:request';
184
+ version: 1;
185
+ sessionId: string;
186
+ requestId: string;
187
+ command: NativeCollaborationCommand;
188
+ }
189
+ interface NativeCollaborationResponse {
190
+ type: 'verentis:collaboration:response';
191
+ version: 1;
192
+ sessionId: string;
193
+ requestId: string;
194
+ result?: NativeSnapshot | NativeSaveResult | null;
195
+ error?: string;
196
+ code?: string;
197
+ }
198
+ declare class NativeCollaborationError extends Error {
199
+ readonly code: string;
200
+ constructor(message: string, code: string);
201
+ }
202
+ declare function isNativeSnapshot(value: unknown): value is NativeSnapshot;
203
+ declare function isNativeSaveResult(value: unknown): value is NativeSaveResult;
204
+ declare function validateNativeCommand(command: NativeCollaborationCommand): void;
205
+ /** Native authority is always selected by the installed workspace host, never by the iframe. */
206
+ declare class NativeCollaborationClient {
207
+ private readonly bridge;
208
+ constructor(bridge: Bridge | null);
209
+ private snapshotRequest;
210
+ join(): Promise<NativeSnapshot>;
211
+ snapshot(): Promise<NativeSnapshot>;
212
+ apply(changes: NativeChangeSet): Promise<NativeSnapshot>;
213
+ presence(value: NativePointer | null): Promise<NativeSnapshot>;
214
+ save(generation: number, correlation: string): Promise<NativeSaveResult>;
215
+ close(): Promise<void>;
216
+ }
217
+
29
218
  interface VerentisMessage {
30
219
  type: `verentis:${string}`;
31
220
  version: 1;
@@ -57,30 +246,30 @@ interface VerentisActionResultMessage extends VerentisMessage {
57
246
  result?: HeaderActionResult;
58
247
  error?: string;
59
248
  }
60
- interface VerentisTokenRefreshedMessage extends VerentisMessage {
61
- type: 'verentis:token:refreshed';
249
+ /**
250
+ * A message from the workspace (typically an agent acting for the user) on a channel the app declares in
251
+ * its manifest `spec.messages`. Handled with `bridge.onHostMessage(channel, handler)`.
252
+ */
253
+ interface VerentisHostMessage extends VerentisMessage {
254
+ type: 'verentis:host:message';
255
+ sessionId: string;
62
256
  requestId: string;
63
- token: TokenInfo;
257
+ channel: string;
258
+ payload?: unknown;
64
259
  }
65
- /** Single-use credential for the installation's independently registered backend. */
66
- interface AppBackendCredential {
67
- delegationId: string;
68
- backendClientId: string;
69
- launchCredential: string;
70
- expiresAt: string;
71
- }
72
- interface VerentisBackendCredentialRequest extends VerentisMessage {
73
- type: 'verentis:backend:request';
74
- requestId: string;
260
+ interface VerentisHostReplyMessage extends VerentisMessage {
261
+ type: 'verentis:host:reply';
75
262
  sessionId: string;
76
- }
77
- interface VerentisBackendCredentialResponse extends VerentisMessage {
78
- type: 'verentis:backend:response';
79
263
  requestId: string;
80
- sessionId: string;
81
- credential?: AppBackendCredential;
264
+ channel: string;
265
+ result?: unknown;
82
266
  error?: string;
83
267
  }
268
+ interface VerentisTokenRefreshedMessage extends VerentisMessage {
269
+ type: 'verentis:token:refreshed';
270
+ requestId: string;
271
+ token: TokenInfo;
272
+ }
84
273
  /** Nonsecret active-document metadata. CODE already holds its own scoped credential. */
85
274
  interface WopiContinuation {
86
275
  sessionId: string;
@@ -163,10 +352,11 @@ interface VerentisDirtyMessage extends VerentisMessage {
163
352
  type: 'verentis:dirty';
164
353
  isDirty: boolean;
165
354
  }
166
- type HostToAppMessage = VerentisInitMessage | VerentisActionInvokeMessage | VerentisTokenRefreshedMessage | VerentisFileChangedMessage | VerentisThemeMessage | VerentisBackendCredentialResponse | VerentisWopiResponse;
167
- type AppToHostMessage = VerentisReadyMessage | VerentisActionsSetMessage | VerentisActionResultMessage | VerentisTokenRefreshMessage | VerentisNavigateMessage | VerentisResizeMessage | VerentisTitleMessage | VerentisDirtyMessage | VerentisBackendCredentialRequest | VerentisWopiRequest;
355
+ type HostToAppMessage = VerentisInitMessage | VerentisActionInvokeMessage | VerentisHostMessage | VerentisTokenRefreshedMessage | VerentisFileChangedMessage | VerentisThemeMessage | VerentisWopiResponse | NativeCollaborationResponse;
356
+ type AppToHostMessage = VerentisReadyMessage | VerentisActionsSetMessage | VerentisActionResultMessage | VerentisHostReplyMessage | VerentisTokenRefreshMessage | VerentisNavigateMessage | VerentisResizeMessage | VerentisTitleMessage | VerentisDirtyMessage | VerentisWopiRequest | NativeCollaborationRequest;
168
357
  type AppSurface = 'file' | 'workspace';
169
358
  interface AppContextBase {
359
+ application?: AppApplicationContext;
170
360
  workspace: WorkspaceInfo;
171
361
  entryPoint?: EntryPointInfo;
172
362
  apiUrl: string;
@@ -177,6 +367,11 @@ interface AppContextBase {
177
367
  wopiEnabled?: boolean;
178
368
  };
179
369
  }
370
+ interface AppApplicationContext {
371
+ manifestPath: string;
372
+ manifestNodeId: string;
373
+ branch: string;
374
+ }
180
375
  /** Context for an application opened against a workspace file. */
181
376
  interface FileAppContext extends AppContextBase {
182
377
  surface: 'file';
@@ -271,6 +466,33 @@ interface FileEntry {
271
466
  version?: string;
272
467
  etag?: string;
273
468
  children?: FileEntry[];
469
+ /** Stable node identity, when supplied by the path metadata API. */
470
+ nodeId?: string;
471
+ }
472
+ interface NodeFileMetadata {
473
+ nodeId: string;
474
+ path: string;
475
+ name: string;
476
+ mimeType: string;
477
+ size?: number | null;
478
+ /** Unquoted opaque content revision; distinct from a path delete head stamp. */
479
+ etag: string;
480
+ version: string;
481
+ children?: PagedResult<FileEntry>;
482
+ }
483
+ interface NodeFileOptions {
484
+ branch: string;
485
+ }
486
+ interface NodeFileContent {
487
+ content: Blob;
488
+ /** Strong quoted ETag returned by the node-content API. */
489
+ revision: string;
490
+ }
491
+ interface WriteNodeFileOptions extends NodeFileOptions {
492
+ content: Blob | string | ArrayBuffer;
493
+ /** Strong quoted revision, or the unquoted etag returned by getNode. */
494
+ revision: string;
495
+ idempotencyKey: string;
274
496
  }
275
497
  interface GetFileOptions {
276
498
  branch?: string;
@@ -283,6 +505,8 @@ interface WriteFileOptions {
283
505
  contentType?: string;
284
506
  filename?: string;
285
507
  branch?: string;
508
+ /** Atomically require no live file at this path; conflicts return HTTP 412. */
509
+ createOnly?: boolean;
286
510
  }
287
511
  interface MoveFileOptions {
288
512
  from: string;
@@ -292,6 +516,10 @@ interface MoveFileOptions {
292
516
  interface DeleteFileOptions {
293
517
  path: string;
294
518
  branch?: string;
519
+ /** Path-binding head stamp, not a node-content revision. */
520
+ headStamp?: string;
521
+ idempotencyKey?: string;
522
+ mode?: 'shallow' | 'deep';
295
523
  }
296
524
  type ArchiveFormat = 'zip' | 'tgz';
297
525
  interface ReadArchiveOptions {
@@ -326,6 +554,64 @@ interface InstalledPackageDescriptor {
326
554
  payloads: InstalledPackagePayload[];
327
555
  }
328
556
  type InstallationMode = 'Extracted' | 'Sealed';
557
+ /** Required dependencies use immutable exact SemVer pins; optional packages are never implicit installs. */
558
+ interface PackageDependency {
559
+ package: string;
560
+ version: string;
561
+ installPath?: string | null;
562
+ optional?: boolean;
563
+ }
564
+ interface InstallationGraphPackage {
565
+ packageId: string;
566
+ packageVersionId: string;
567
+ publisherId: string;
568
+ identity: string;
569
+ publisher: string;
570
+ version: string;
571
+ treeDigest: string;
572
+ artifactFingerprint: string;
573
+ manifestYaml: string;
574
+ verifiedSigningKeyKid?: string | null;
575
+ branch: string;
576
+ installPath: string;
577
+ installMode: InstallationMode;
578
+ reuseInstallationId?: string | null;
579
+ /** Only a previously Failed exact target can be recovered, after a fresh explicit preview. */
580
+ retryInstallationId?: string | null;
581
+ permissions: string[];
582
+ dependencies: PackageDependency[];
583
+ /** Conservative destination reservations, including external install-map/seed roots. */
584
+ installPaths: string[];
585
+ }
586
+ interface InstallationGraphPreview {
587
+ operationId: string;
588
+ workspaceId: string;
589
+ expiresAt: string;
590
+ fingerprint: string;
591
+ /** Topological installation order: required dependencies before their dependents. */
592
+ packages: InstallationGraphPackage[];
593
+ }
594
+ type InstallationGraphOutcomeStatus = 'Pending' | 'Installing' | 'Reused' | 'Installed' | 'InstalledWithError' | 'Failed' | 'NotAttempted';
595
+ interface InstallationGraphResult {
596
+ operationId: string;
597
+ status: 'Preview' | 'Accepted' | 'Completed' | 'Rejected' | 'Failed';
598
+ succeeded: boolean;
599
+ /** The exact durable preview baseline, also available after a lost preview/install response. */
600
+ packages: InstallationGraphPackage[];
601
+ outcomes: {
602
+ identity: string;
603
+ status: InstallationGraphOutcomeStatus;
604
+ installationId?: string | null;
605
+ error?: string | null;
606
+ }[];
607
+ error?: string | null;
608
+ }
609
+ interface PreviewInstallationOptions extends InstallationScopedOptions {
610
+ packageVersion?: string;
611
+ installPath?: string;
612
+ branch?: string;
613
+ installMode?: InstallationMode;
614
+ }
329
615
  type InstallationStatus = 'Pending' | 'Installing' | 'Installed' | 'Updating' | 'Uninstalling' | 'Failed' | 'Uninstalled';
330
616
  interface Installation {
331
617
  id: string;
@@ -505,6 +791,9 @@ interface ApplicationEntryPoint {
505
791
  display?: ApplicationDisplayOptions;
506
792
  }
507
793
  interface ApplicationSpec {
794
+ dependencies?: PackageDependency[];
795
+ /** Publisher-qualified required engine dependency for script-bearing packages. */
796
+ engine?: string;
508
797
  /** Optional iframe UI surface URL. Omit for a headless / file-collection app. */
509
798
  entry?: string;
510
799
  /** Optional application splash URL. Relative values resolve against the selected iframe entry URL. */
@@ -831,7 +1120,8 @@ declare class ApiError extends Error {
831
1120
  readonly status: number;
832
1121
  readonly detail: string;
833
1122
  readonly title?: string | undefined;
834
- constructor(status: number, detail: string, title?: string | undefined);
1123
+ readonly code?: string | undefined;
1124
+ constructor(status: number, detail: string, title?: string | undefined, code?: string | undefined);
835
1125
  }
836
1126
 
837
1127
  /**
@@ -845,6 +1135,8 @@ declare class ContextModule {
845
1135
  private _file;
846
1136
  private _entryPoint;
847
1137
  private _apiUrl;
1138
+ private _application;
1139
+ private _installation;
848
1140
  /** The current workspace */
849
1141
  get workspace(): WorkspaceInfo;
850
1142
  /** The host surface that launched the app */
@@ -859,6 +1151,8 @@ declare class ContextModule {
859
1151
  get entryPoint(): EntryPointInfo | null;
860
1152
  /** Whether an entry point context is available */
861
1153
  get hasEntryPoint(): boolean;
1154
+ get application(): AppApplicationContext | null;
1155
+ get installation(): AppContext['installation'] | null;
862
1156
  /** Update context from the host's init message */
863
1157
  setFromAppContext(ctx: AppContext): void;
864
1158
  /** Set workspace info directly (standalone mode) */
@@ -881,6 +1175,7 @@ declare class HttpTransport {
881
1175
  constructor(baseUrl: string, auth: AuthStrategy, apiVersion?: string);
882
1176
  request<T>(method: string, path: string, options?: RequestOptions): Promise<T>;
883
1177
  requestRaw(method: string, path: string, options?: RequestOptions): Promise<Response>;
1178
+ ensureSuccess(response: Response): Promise<void>;
884
1179
  private buildUrl;
885
1180
  }
886
1181
 
@@ -950,6 +1245,12 @@ declare class FilesModule {
950
1245
  * For directories: returns metadata with children array populated.
951
1246
  */
952
1247
  get(path: string, options?: GetFileOptions): Promise<FileEntry>;
1248
+ /** Read metadata by stable node identity on an explicit branch. */
1249
+ getNode(nodeId: string, options: NodeFileOptions): Promise<NodeFileMetadata>;
1250
+ /** Read bytes and their matching content revision in the same response. */
1251
+ readNodeContent(nodeId: string, options: NodeFileOptions): Promise<NodeFileContent>;
1252
+ /** Replace existing node bytes conditionally; never creates or changes path/MIME. */
1253
+ writeNodeContent(nodeId: string, options: WriteNodeFileOptions): Promise<NodeFileMetadata>;
953
1254
  /**
954
1255
  * Read the raw content of a file as a Blob.
955
1256
  */
@@ -973,6 +1274,8 @@ declare class FilesModule {
973
1274
  * Upload or create a file.
974
1275
  */
975
1276
  write(path: string, options: WriteFileOptions): Promise<void>;
1277
+ /** Create without a read-before-write race or overwrite of an existing live file. */
1278
+ create(path: string, options: WriteFileOptions): Promise<void>;
976
1279
  /**
977
1280
  * Move or rename a file.
978
1281
  */
@@ -989,6 +1292,14 @@ declare class InstallationsModule {
989
1292
  private readonly http;
990
1293
  private readonly workspaceId?;
991
1294
  constructor(http: HttpTransport, workspaceId?: string | undefined);
1295
+ /** Resolve canonical publisher/package identity, never the installation's runtime display name. */
1296
+ resolvePackageId(identity: string, options?: InstallationScopedOptions): Promise<string>;
1297
+ /** Resolves the complete required graph without installing anything or granting capabilities. */
1298
+ preview(packageId: string, options?: PreviewInstallationOptions): Promise<InstallationGraphPreview>;
1299
+ /** Explicit, single-use consent to a displayed preview. Never automatically retries accepted installs. */
1300
+ install(preview: InstallationGraphPreview, consent: true): Promise<InstallationGraphResult>;
1301
+ /** Inspect durable outcomes after a failure or lost response instead of resubmitting consent. */
1302
+ graphResult(operationId: string, options?: InstallationScopedOptions): Promise<InstallationGraphResult>;
992
1303
  list(options?: InstallationListOptions): Promise<PagedResult<Installation>>;
993
1304
  resolve(installPath: string, options?: ResolveInstallationOptions): Promise<InstallationDetail>;
994
1305
  update(id: string, options?: UpdateInstallationOptions): Promise<InstallationLifecycleResult>;
@@ -1058,74 +1369,257 @@ interface NamespacedSettings {
1058
1369
  reset(key: string, options?: SettingsScopedOptions): Promise<void>;
1059
1370
  }
1060
1371
 
1061
- type BridgeEventType = HostToAppMessage['type'];
1062
- type BridgeListener = (data: HostToAppMessage) => void;
1372
+ interface EmailScopedOptions {
1373
+ workspaceId?: string;
1374
+ branch?: 'main';
1375
+ }
1376
+ interface EmailHistoryOptions extends EmailScopedOptions {
1377
+ recordId?: string;
1378
+ installationId?: string;
1379
+ }
1380
+ interface EmailPurpose {
1381
+ name: string;
1382
+ templateId: string;
1383
+ maximumRecipients: number;
1384
+ maximumAttachmentBytes: number;
1385
+ allowsOpenTracking: boolean;
1386
+ allowsClickTracking: boolean;
1387
+ senderRequirement: 'workspace-owned' | 'managed-or-workspace';
1388
+ }
1389
+ interface EmailSenderGrant {
1390
+ purpose: string;
1391
+ senderId: string;
1392
+ senderIdentityDigest?: string;
1393
+ }
1394
+ interface EmailConsentPreview {
1395
+ installationId: string;
1396
+ workspaceId: string;
1397
+ accountId: string;
1398
+ packageId: string;
1399
+ packageVersionId: string;
1400
+ publisherId: string;
1401
+ publisherName: string;
1402
+ version: string;
1403
+ treeDigest: string;
1404
+ signingKeyId: string;
1405
+ installPath: string;
1406
+ branch: string;
1407
+ candidateDigest: string;
1408
+ declaration: {
1409
+ purposes: EmailPurpose[];
1410
+ maximumMessagesPerHour: number;
1411
+ permissions: string[];
1412
+ scopes: string[];
1413
+ manifestDigest: string;
1414
+ };
1415
+ }
1416
+ interface EmailConsent {
1417
+ installationId: string;
1418
+ candidateDigest: string;
1419
+ enabled: boolean;
1420
+ allowOpenTracking: boolean;
1421
+ allowClickTracking: boolean;
1422
+ approvedBy: string;
1423
+ updatedAt: string;
1424
+ senderGrants: EmailSenderGrant[] | null;
1425
+ }
1426
+ interface EmailConsentOptions {
1427
+ senderGrants: EmailSenderGrant[];
1428
+ allowOpenTracking?: boolean;
1429
+ allowClickTracking?: boolean;
1430
+ }
1431
+ interface EmailSenderIdentity {
1432
+ id: string;
1433
+ mode: 'managed' | 'custom';
1434
+ displayName: string;
1435
+ address: string;
1436
+ }
1437
+ interface EmailArtifactOutcome {
1438
+ artifactId: string;
1439
+ sha256: string;
1440
+ byteLength: number;
1441
+ fileName: string;
1442
+ }
1443
+ interface EmailDispatchOptions extends EmailScopedOptions {
1444
+ installationId: string;
1445
+ recordId: string;
1446
+ purpose: string;
1447
+ templateId: string;
1448
+ senderId: string;
1449
+ recipients: string[];
1450
+ artifactIds: string[];
1451
+ idempotencyKey: string;
1452
+ replyTo?: string;
1453
+ }
1454
+ interface EmailDispatchOutcome {
1455
+ id: string;
1456
+ status: 'accepted' | 'delivered' | 'failed' | 'unknown';
1457
+ createdAt: string;
1458
+ failureCode?: string | null;
1459
+ recordId: string;
1460
+ installationId: string;
1461
+ branch: 'main';
1462
+ purpose: string;
1463
+ templateId: string;
1464
+ events: EmailDeliveryEvidence[];
1465
+ }
1466
+ interface EmailDeliveryEvidence {
1467
+ type: 'processed' | 'deferred' | 'delivered' | 'failed' | 'complaint' | 'unsubscribe' | 'open' | 'click';
1468
+ occurredAt: string;
1469
+ }
1470
+
1471
+ /** Signed-package transactional email. Dispatch never accepts HTML, From or a browser invoice snapshot. */
1472
+ declare class EmailModule {
1473
+ private readonly http;
1474
+ private readonly workspaceId?;
1475
+ constructor(http: HttpTransport, workspaceId?: string | undefined);
1476
+ preview(installationId: string, options?: EmailScopedOptions): Promise<EmailConsentPreview>;
1477
+ consents(options?: EmailScopedOptions): Promise<EmailConsent[]>;
1478
+ /** Approve exactly the reviewed signed candidate; tracking stays off unless explicitly opted in. */
1479
+ consent(preview: EmailConsentPreview, approval: true, options: EmailConsentOptions): Promise<EmailConsent>;
1480
+ revoke(consent: EmailConsent, options?: EmailScopedOptions): Promise<EmailConsent>;
1481
+ senders(options?: EmailScopedOptions): Promise<EmailSenderIdentity[]>;
1482
+ invoicePdf(recordId: string, installationId: string, options?: EmailScopedOptions): Promise<EmailArtifactOutcome>;
1483
+ /** Authenticated immutable bytes; no public URL. The caller owns any local object URL it creates. */
1484
+ artifactContent(artifactId: string, options?: EmailScopedOptions): Promise<Blob>;
1485
+ /** A stable key binds this exact request. After a lost response inspect status; never automatically resend. */
1486
+ dispatch(options: EmailDispatchOptions): Promise<EmailDispatchOutcome>;
1487
+ outcome(id: string, options?: EmailScopedOptions): Promise<EmailDispatchOutcome>;
1488
+ history(options?: EmailHistoryOptions): Promise<EmailDispatchOutcome[]>;
1489
+ status(id: string, options?: EmailScopedOptions): Promise<EmailDispatchOutcome>;
1490
+ private workspace;
1491
+ private mainBranch;
1492
+ }
1493
+
1494
+ type BusinessOperation = 'save-record' | 'archive-record' | 'delete-record' | 'restore-record' | 'close-period' | 'issue-invoice' | 'credit-invoice' | 'post-payment' | 'reverse-payment' | 'post-journal' | 'reverse-journal' | 'post-expense' | 'reverse-expense';
1495
+ interface BusinessParameters {
1496
+ periodId?: string;
1497
+ receivableAccountId?: string;
1498
+ incomeAccountId?: string;
1499
+ taxAccountId?: string;
1500
+ date?: string;
1501
+ reason?: string;
1502
+ }
1503
+ interface BusinessCommand {
1504
+ operation: BusinessOperation;
1505
+ idempotencyKey: string;
1506
+ /** Omit only when creating; the server derives a stable ID from this operation key. */
1507
+ recordId?: string;
1508
+ /** Canonical kind, e.g. crm/company. Required for metadata-free creation. */
1509
+ kind?: string;
1510
+ expectedCatalogueRevision?: string;
1511
+ /** Exact strong, quoted canonical revision; omit only for a new record. */
1512
+ expectedRevision?: string;
1513
+ record?: Record<string, unknown>;
1514
+ parameters?: BusinessParameters;
1515
+ }
1516
+ interface BusinessSnapshot {
1517
+ id: string;
1518
+ kind: string;
1519
+ json: string;
1520
+ revision: string;
1521
+ }
1522
+ interface BusinessContext {
1523
+ workspaceId: string;
1524
+ branch: string;
1525
+ catalogueRevision: string | null;
1526
+ settings: BusinessSnapshot[];
1527
+ }
1528
+ interface BusinessCommitResult {
1529
+ operationId: string;
1530
+ committedAt: string;
1531
+ records: BusinessSnapshot[];
1532
+ }
1533
+ interface BusinessOutcomeRequest {
1534
+ operation: BusinessOperation;
1535
+ idempotencyKey: string;
1536
+ requestHash?: string;
1537
+ command?: BusinessCommand;
1538
+ }
1539
+ type BusinessReportName = 'trial-balance' | 'general-ledger' | 'profit-and-loss' | 'balance-sheet' | 'receivables';
1540
+ interface BusinessReportLine {
1541
+ accountId: string;
1542
+ code: string;
1543
+ name: string;
1544
+ accountType: 'asset' | 'liability' | 'equity' | 'income' | 'expense';
1545
+ debitMinor: string;
1546
+ creditMinor: string;
1547
+ balanceMinor: string;
1548
+ }
1549
+ interface BusinessReport {
1550
+ report: BusinessReportName;
1551
+ from: string | null;
1552
+ to: string | null;
1553
+ lines: BusinessReportLine[];
1554
+ entries: BusinessLedgerEntry[];
1555
+ /** Coherent catalogue revision and overdue evaluation date for receivables. */
1556
+ revision?: string;
1557
+ asOf?: string;
1558
+ currency?: string;
1559
+ minorDigits?: number;
1560
+ receivables?: BusinessReceivable[];
1561
+ totals?: BusinessReceivableTotals;
1562
+ }
1563
+ interface BusinessReceivable {
1564
+ invoiceId: string;
1565
+ revision: string;
1566
+ invoiceNumber: string;
1567
+ issueDate: string;
1568
+ dueDate: string;
1569
+ currency: string;
1570
+ minorDigits: number;
1571
+ customer: Record<string, unknown>;
1572
+ customerReference?: Record<string, unknown>;
1573
+ grossAmountMinor: string;
1574
+ creditedAmountMinor: string;
1575
+ paidAmountMinor: string;
1576
+ outstandingAmountMinor: string;
1577
+ overdueAmountMinor: string;
1578
+ isOverdue: boolean;
1579
+ daysOverdue: number;
1580
+ }
1581
+ interface BusinessReceivableTotals {
1582
+ grossAmountMinor: string;
1583
+ creditedAmountMinor: string;
1584
+ paidAmountMinor: string;
1585
+ outstandingAmountMinor: string;
1586
+ overdueAmountMinor: string;
1587
+ }
1588
+ interface BusinessLedgerEntry {
1589
+ journalId: string;
1590
+ date: string;
1591
+ description: string;
1592
+ accountId: string;
1593
+ direction: 'debit' | 'credit';
1594
+ amountMinor: string;
1595
+ runningBalanceMinor: string;
1596
+ }
1597
+
1063
1598
  /**
1064
- * PostMessage bridge for communication between an app (iframe) and the
1065
- * workspace host. Handles the initialization handshake, token lifecycle,
1066
- * and app-to-host events (navigate, resize, dirty, etc.).
1599
+ * Trusted workspace business records, independent of app scripts or generic file writes.
1600
+ * Never automatically retries a command: resolve a lost response with outcome() or
1601
+ * resubmit the exact same command/key to obtain the original durable result.
1067
1602
  */
1068
- declare class Bridge {
1069
- private readonly expectedHostOrigin?;
1070
- private listeners;
1071
- private _initResolve;
1072
- private _initReject;
1073
- private _initTimer;
1074
- private _initPromise;
1075
- private _hostOrigin;
1076
- private _messageHandler;
1077
- private _destroyed;
1078
- private sessionId;
1079
- private actions;
1080
- private requests;
1081
- private backendRequests;
1082
- private wopiRequests;
1083
- constructor(expectedHostOrigin?: string | undefined);
1084
- /** Post `verentis:ready` to the host to start the handshake */
1085
- sendReady(capabilities?: string[]): void;
1086
- /** Wait for the host to send `verentis:init` with context and token */
1087
- waitForInit(): Promise<{
1088
- context: AppContext;
1089
- token: TokenInfo;
1090
- }>;
1091
- /** Get the host origin (available after init) */
1092
- get hostOrigin(): string | null;
1093
- /** Send a message to the host */
1094
- postToHost(message: AppToHostMessage): void;
1095
- /**
1096
- * Navigate to another location in the workspace.
1097
- *
1098
- * @param path A workspace file path (e.g. `/reports/q1.json`) or an absolute
1099
- * http(s) URL. External URLs require the app to declare the
1100
- * `navigation:external` capability in its manifest.
1101
- * @param options Navigation options. Set `newTab: true` to open the target in
1102
- * a new browser tab instead of the current one.
1103
- */
1104
- navigate(path: string, options?: NavigateOptions): void;
1105
- /** Request iframe resize */
1106
- resize(height: number): void;
1107
- /** Update the title displayed by the host */
1108
- setTitle(title: string): void;
1109
- /** Signal unsaved changes to the host */
1110
- setDirty(isDirty: boolean): void;
1111
- /** The host, not the app, selects the installation, file, branch and permission ceiling. */
1112
- requestBackendCredential(): Promise<AppBackendCredential>;
1113
- /** The trusted parent selects the approved installation, document and action. */
1114
- requestWopiLaunch(): Promise<WopiLaunch>;
1115
- /** Recover only the target selected by a completed server-owned derived operation. */
1116
- requestWopiContinuation(): Promise<WopiContinuation>;
1117
- getWopiStatus(): Promise<WopiSaveStatus>;
1118
- requestWopiSave(generation: number): Promise<WopiSaveCheckpoint>;
1119
- closeWopiSession(): Promise<void>;
1120
- private requestWopi;
1121
- registerAction(descriptor: HeaderAction, handler: HeaderActionHandler): HeaderActionRegistration;
1122
- private publishActions;
1123
- private invokeAction;
1124
- /** Subscribe to a specific message type from the host */
1125
- on(type: BridgeEventType, listener: BridgeListener): () => void;
1126
- /** Clean up event listeners */
1127
- destroy(): void;
1128
- private handleMessage;
1603
+ declare class BusinessModule {
1604
+ private readonly http;
1605
+ private readonly branch;
1606
+ constructor(http: HttpTransport, branch?: string);
1607
+ withBranch(branch: string): BusinessModule;
1608
+ context(): Promise<BusinessContext>;
1609
+ command(command: BusinessCommand): Promise<BusinessCommitResult>;
1610
+ read(id: string): Promise<BusinessSnapshot | null>;
1611
+ list(kind?: string): Promise<BusinessSnapshot[]>;
1612
+ /** null means unresolved, not success; do not invent a new operation key. */
1613
+ outcome(request: BusinessOutcomeRequest): Promise<BusinessCommitResult | null>;
1614
+ /** Recover using the exact original command, without reproducing server fingerprint encoding. */
1615
+ outcomeFor(command: BusinessCommand): Promise<BusinessCommitResult | null>;
1616
+ report(report: BusinessReportName, range?: {
1617
+ from?: string;
1618
+ to?: string;
1619
+ }): Promise<BusinessReport>;
1620
+ /** Retained historical expense receipt bytes, even after the original native file is removed. */
1621
+ receipt(nodeId: string, revision: string): Promise<Blob>;
1622
+ private headers;
1129
1623
  }
1130
1624
 
1131
1625
  /**
@@ -1140,8 +1634,11 @@ declare class VerentisClient {
1140
1634
  installations: InstallationsModule;
1141
1635
  resources: ResourcesModule;
1142
1636
  settings: SettingsModule;
1637
+ email: EmailModule;
1638
+ business: BusinessModule;
1143
1639
  readonly context: ContextModule;
1144
1640
  readonly bridge: Bridge | null;
1641
+ readonly collaboration: NativeCollaborationClient;
1145
1642
  private readonly _auth;
1146
1643
  private _http;
1147
1644
  private _ready;
@@ -1152,6 +1649,12 @@ declare class VerentisClient {
1152
1649
  * In iframe mode this resolves after the host sends `verentis:init`.
1153
1650
  */
1154
1651
  whenReady(): Promise<void>;
1652
+ /**
1653
+ * The current `Authorization` header value, refreshed when near expiry.
1654
+ * Forward it to the app's own backend, which exchanges it at Security's
1655
+ * `/connect/token` (RFC 8693) as the installation's confidential client.
1656
+ */
1657
+ getAuthorizationHeader(): Promise<string | null>;
1155
1658
  /** Clean up resources (timers, event listeners) */
1156
1659
  destroy(): void;
1157
1660
  private initFromBridge;
@@ -1170,6 +1673,36 @@ declare function matchMimeType(pattern: string, mimeType: string): boolean;
1170
1673
  */
1171
1674
  declare function findBestMatch(mimeType: string, bindings: MimeTypeBinding[]): MimeTypeBinding | null;
1172
1675
 
1676
+ interface CollaborationDocumentContext {
1677
+ workspace?: {
1678
+ id?: string;
1679
+ };
1680
+ file?: {
1681
+ nodeId?: string;
1682
+ branch?: string;
1683
+ };
1684
+ }
1685
+ interface CollaborationDocument {
1686
+ sessionId: string;
1687
+ workspaceId: string;
1688
+ branch: string;
1689
+ nodeId: string;
1690
+ fileId: string;
1691
+ name: string;
1692
+ readOnly: boolean;
1693
+ accessTokenTtl: number;
1694
+ }
1695
+ /** An exact origin, not a URL pattern or an authority grant. */
1696
+ declare function exactHttpsOrigin(value: unknown): string;
1697
+ declare function isTrustedMessage(event: {
1698
+ source: unknown;
1699
+ origin: string;
1700
+ }, source: unknown, origin: string): boolean;
1701
+ /** Checks nonsecret launch metadata against the document selected by the trusted host. */
1702
+ declare function validateCollaborationDocument(value: unknown, context: CollaborationDocumentContext, now?: number): CollaborationDocument;
1703
+ /** An editor acknowledgement alone never proves a document was durably saved. */
1704
+ declare function isDurableSaveConfirmed(result: unknown, request: unknown, currentGeneration: number, editorModified: boolean): boolean;
1705
+
1173
1706
  /**
1174
1707
  * Authenticates with a Verentis API key (`vrt_` prefix).
1175
1708
  * The backend detects the `vrt_` prefix in the Bearer token and resolves it
@@ -1257,4 +1790,4 @@ declare class BridgeAuth implements AuthStrategy {
1257
1790
  */
1258
1791
  declare function createVerentisClient(options?: VerentisClientOptions): VerentisClient;
1259
1792
 
1260
- export { ApiError, ApiKeyAuth, type AppBackendCredential, type AppContext, type AppSurface, type AppToHostMessage, type ApplicationDisplayOptions, type ApplicationEntryPoint, type ApplicationFileType, type ApplicationLaunchConfig, type ApplicationManifest, type ApplicationSpec, type ArchiveFormat, type AuthOptions, type AuthStrategy, Bridge, BridgeAuth, type CatalogImage, ContextModule, type DeleteFileOptions, type EngineFileType, type EngineRuntime, type EngineTool, EnginesModule, type EntryPointInfo, type ExecuteEngineOptions, type Execution, type ExecutionEngine, type ExecutionEngineListOptions, type ExecutionListOptions, type ExecutionLogs, type ExecutionMode, type ExecutionResult, type ExecutionScopedOptions, type ExecutionStatus, type ExecutionTrigger, ExecutionsModule, type ExtractUploadOptions, type FileAppContext, type FileEntry, type FileInfo, FilesModule, type GetFileOptions, type HeaderAction, type HeaderActionHandler, type HeaderActionRegistration, type HeaderActionResult, type HostToAppMessage, HttpTransport, type Installation, type InstallationDetail, type InstallationLifecycleResult, type InstallationListOptions, type InstallationMode, type InstallationScopedOptions, type InstallationStatus, InstallationsModule, type InstalledPackageDescriptor, type InstalledPackagePayload, type ManifestMetadata, type MimeTypeBinding, type MoveFileOptions, type NamespacedSettings, type NavigateOptions, type OAuthConfig, type PagedResult, type ReadArchiveOptions, type RequestOptions, type ResolveInstallationOptions, type ResourceMimeTypeBinding, type ResourceRegistration, type ResourceScopedOptions, ResourcesModule, type RunFileOptions, type SandboxOptions, type SettingDeclaration, type SettingDeclarationType, type SettingGroup, type SettingItem, type SettingOption, type SettingPresence, SettingsModule, type SettingsScopedOptions, TokenAuth, type TokenInfo, type UpdateInstallationOptions, type VerentisActionInvokeMessage, type VerentisActionResultMessage, type VerentisActionsSetMessage, type VerentisBackendCredentialRequest, type VerentisBackendCredentialResponse, VerentisClient, type VerentisClientOptions, type VerentisDirtyMessage, type VerentisFileChangedMessage, type VerentisInitMessage, type VerentisMessage, type VerentisNavigateMessage, type VerentisReadyMessage, type VerentisResizeMessage, type VerentisThemeMessage, type VerentisTitleMessage, type VerentisTokenRefreshMessage, type VerentisTokenRefreshedMessage, type VerentisWopiRequest, type VerentisWopiResponse, type WaitOptions, type WopiContinuation, type WopiLaunch, type WopiSaveCheckpoint, type WopiSaveStatus, type WorkspaceAppContext, type WorkspaceInfo, type WriteFileOptions, createVerentisClient, findBestMatch, isHeaderAction, isTerminalStatus, matchMimeType };
1793
+ export { ApiError, ApiKeyAuth, type AppApplicationContext, type AppContext, type AppSurface, type AppToHostMessage, type ApplicationDisplayOptions, type ApplicationEntryPoint, type ApplicationFileType, type ApplicationLaunchConfig, type ApplicationManifest, type ApplicationSpec, type ArchiveFormat, type AuthOptions, type AuthStrategy, Bridge, BridgeAuth, type BusinessCommand, type BusinessCommitResult, type BusinessContext, type BusinessLedgerEntry, BusinessModule, type BusinessOperation, type BusinessOutcomeRequest, type BusinessParameters, type BusinessReceivable, type BusinessReceivableTotals, type BusinessReport, type BusinessReportLine, type BusinessReportName, type BusinessSnapshot, type CatalogImage, type CollaborationDocument, type CollaborationDocumentContext, ContextModule, type DeleteFileOptions, type EmailArtifactOutcome, type EmailConsent, type EmailConsentOptions, type EmailConsentPreview, type EmailDeliveryEvidence, type EmailDispatchOptions, type EmailDispatchOutcome, type EmailHistoryOptions, EmailModule, type EmailPurpose, type EmailScopedOptions, type EmailSenderGrant, type EmailSenderIdentity, type EngineFileType, type EngineRuntime, type EngineTool, EnginesModule, type EntryPointInfo, type ExecuteEngineOptions, type Execution, type ExecutionEngine, type ExecutionEngineListOptions, type ExecutionListOptions, type ExecutionLogs, type ExecutionMode, type ExecutionResult, type ExecutionScopedOptions, type ExecutionStatus, type ExecutionTrigger, ExecutionsModule, type ExtractUploadOptions, type FileAppContext, type FileEntry, type FileInfo, FilesModule, type GetFileOptions, HOST_MESSAGE_CHANNEL_PATTERN, type HeaderAction, type HeaderActionHandler, type HeaderActionRegistration, type HeaderActionResult, type HostMessageHandler, type HostToAppMessage, HttpTransport, type Installation, type InstallationDetail, type InstallationGraphOutcomeStatus, type InstallationGraphPackage, type InstallationGraphPreview, type InstallationGraphResult, type InstallationLifecycleResult, type InstallationListOptions, type InstallationMode, type InstallationScopedOptions, type InstallationStatus, InstallationsModule, type InstalledPackageDescriptor, type InstalledPackagePayload, type ManifestMetadata, type MimeTypeBinding, type MoveFileOptions, type NamespacedSettings, type NativeChangeSet, NativeCollaborationClient, type NativeCollaborationCommand, NativeCollaborationError, type NativeCollaborationRequest, type NativeCollaborationResponse, type NativeElement, type NativeFile, type NativeParticipant, type NativePointer, type NativeSaveReceipt, type NativeSaveResult, type NativeScene, type NativeSnapshot, type NavigateOptions, type NodeFileContent, type NodeFileMetadata, type NodeFileOptions, type OAuthConfig, type PackageDependency, type PagedResult, type PreviewInstallationOptions, type ReadArchiveOptions, type RequestOptions, type ResolveInstallationOptions, type ResourceMimeTypeBinding, type ResourceRegistration, type ResourceScopedOptions, ResourcesModule, type RunFileOptions, type SandboxOptions, type SettingDeclaration, type SettingDeclarationType, type SettingGroup, type SettingItem, type SettingOption, type SettingPresence, SettingsModule, type SettingsScopedOptions, TokenAuth, type TokenInfo, type UpdateInstallationOptions, type VerentisActionInvokeMessage, type VerentisActionResultMessage, type VerentisActionsSetMessage, VerentisClient, type VerentisClientOptions, type VerentisDirtyMessage, type VerentisFileChangedMessage, type VerentisHostMessage, type VerentisHostReplyMessage, type VerentisInitMessage, type VerentisMessage, type VerentisNavigateMessage, type VerentisReadyMessage, type VerentisResizeMessage, type VerentisThemeMessage, type VerentisTitleMessage, type VerentisTokenRefreshMessage, type VerentisTokenRefreshedMessage, type VerentisWopiRequest, type VerentisWopiResponse, type WaitOptions, type WopiContinuation, type WopiLaunch, type WopiSaveCheckpoint, type WopiSaveStatus, type WorkspaceAppContext, type WorkspaceInfo, type WriteFileOptions, type WriteNodeFileOptions, createVerentisClient, exactHttpsOrigin, findBestMatch, isDurableSaveConfirmed, isHeaderAction, isNativeSaveResult, isNativeSnapshot, isTerminalStatus, isTrustedMessage, matchMimeType, validateCollaborationDocument, validateNativeCommand };