@centrali-io/centrali-sdk 6.6.0 → 6.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -285,6 +285,11 @@ declare function getAllowedDomainsApiPath(workspaceId: string, domainId?: string
285
285
  * Generate Webhook Subscriptions API URL PATH.
286
286
  */
287
287
  declare function getWebhookSubscriptionsApiPath(workspaceId: string, subscriptionId?: string): string;
288
+ /**
289
+ * Generate the payload-versions API URL PATH. Lists the outbound payload
290
+ * versions a subscription can be pinned to.
291
+ */
292
+ declare function getWebhookPayloadVersionsApiPath(workspaceId: string): string;
288
293
  /**
289
294
  * Generate rotate-secret API URL PATH for a webhook subscription.
290
295
  */
@@ -2339,6 +2344,8 @@ interface FunctionRun {
2339
2344
  triggerType?: string | null;
2340
2345
  orchestrationRunId?: string | null;
2341
2346
  orchestrationStepId?: string | null;
2347
+ /** Inbound durable buffer link (CEN-1297) — set for buffered webhook-trigger runs. */
2348
+ inboundEventId?: string | null;
2342
2349
  originalRunId?: string | null;
2343
2350
  isRerun: boolean;
2344
2351
  rerunCount: number;
@@ -2693,6 +2700,20 @@ interface WebhookSubscription {
2693
2700
  * undefined on subsequent reads so it is safe to pass subscriptions around.
2694
2701
  */
2695
2702
  secret?: string;
2703
+ /**
2704
+ * Outbound payload version this subscription receives — a date-string
2705
+ * (`YYYY-MM`). Deliveries are projected into the shape this version
2706
+ * describes. Frozen at creation; change it to upgrade to a newer shape.
2707
+ */
2708
+ payloadVersion: string;
2709
+ /**
2710
+ * Opaque builder-supplied tenant identifier. Carried onto outbound
2711
+ * delivery rows by the platform so embeds and tenant-scoped views can
2712
+ * filter to a single customer without leaking cross-tenant events.
2713
+ * Centrali never parses or interprets this value — it's the builder's
2714
+ * own customer/account/workspace id, whatever shape that takes.
2715
+ */
2716
+ tenantId?: string | null;
2696
2717
  workspaceSlug: string;
2697
2718
  createdAt?: string;
2698
2719
  updatedAt?: string;
@@ -2716,6 +2737,8 @@ interface WebhookDelivery {
2716
2737
  responseBody?: string | null;
2717
2738
  /** Delivery ID the row was replayed from, or null for original deliveries. */
2718
2739
  replayedFrom?: string | null;
2740
+ /** Outbound payload version this delivery was projected into and served with. */
2741
+ payloadVersion: string;
2719
2742
  createdAt: string;
2720
2743
  updatedAt: string;
2721
2744
  }
@@ -2732,6 +2755,19 @@ interface CreateWebhookSubscriptionInput {
2732
2755
  /** Optional — restrict to a subset of collections. Omit for all collections. */
2733
2756
  recordSlugs?: string[];
2734
2757
  active?: boolean;
2758
+ /**
2759
+ * Optional outbound payload version to pin the subscription to. Omit to
2760
+ * freeze to the latest version at creation time. Must be a value returned
2761
+ * by `getPayloadVersions()`.
2762
+ */
2763
+ payloadVersion?: string;
2764
+ /**
2765
+ * Optional opaque tenant identifier — typically the builder's own
2766
+ * customer or account id. Surfaces on every delivery the subscription
2767
+ * produces so tenant-scoped views (e.g. an embedded Event Log) can
2768
+ * filter to one customer.
2769
+ */
2770
+ tenantId?: string | null;
2735
2771
  }
2736
2772
  interface UpdateWebhookSubscriptionInput {
2737
2773
  name?: string;
@@ -2744,6 +2780,26 @@ interface UpdateWebhookSubscriptionInput {
2744
2780
  */
2745
2781
  recordSlugs?: string[];
2746
2782
  active?: boolean;
2783
+ /**
2784
+ * Upgrade (or downgrade) the outbound payload version. Must be a value
2785
+ * returned by `getPayloadVersions()`. Omit to leave the version unchanged.
2786
+ */
2787
+ payloadVersion?: string;
2788
+ /**
2789
+ * Update the opaque tenant identifier. Pass `null` to clear it; omit to
2790
+ * leave it unchanged. Past deliveries are not retroactively rewritten —
2791
+ * the new value applies to deliveries created after the update.
2792
+ */
2793
+ tenantId?: string | null;
2794
+ }
2795
+ /**
2796
+ * Outbound payload versions a subscription can be pinned to. Returned by
2797
+ * `getPayloadVersions()`. `versions` is oldest-first; `latest` is what a
2798
+ * subscription created without an explicit version is frozen to.
2799
+ */
2800
+ interface WebhookPayloadVersions {
2801
+ versions: string[];
2802
+ latest: string;
2747
2803
  }
2748
2804
  interface ListWebhookDeliveriesOptions {
2749
2805
  status?: WebhookDeliveryStatus;
@@ -2802,6 +2858,66 @@ interface AddAllowedDomainOptions {
2802
2858
  domain: string;
2803
2859
  }
2804
2860
 
2861
+ /**
2862
+ * Types for the Event Log embed surface (CEN-1301).
2863
+ *
2864
+ * Mirrors the request/response shapes defined by IAM at
2865
+ * services/backend/iam/src/controllers/embedTokenController.ts.
2866
+ * Keep field names in sync with that controller's Zod schemas.
2867
+ */
2868
+ /**
2869
+ * Capabilities that can be encoded into an embed token.
2870
+ *
2871
+ * - `events:read` — list + retrieve event-log rows for the tenant.
2872
+ * IAM unconditionally injects this on every minted token, so omitting
2873
+ * `capabilities` is equivalent to `['events:read']`.
2874
+ * - `events:replay` — allow the iframe to replay a failed delivery. The
2875
+ * issuing service account must also hold `webhook-subscriptions:replay`.
2876
+ */
2877
+ type EmbedCapability = 'events:read' | 'events:replay';
2878
+ interface IssueEmbedTokenInput {
2879
+ /**
2880
+ * Tenant id the embed is allowed to read. Burned into the token claim;
2881
+ * the data-service auto-injects this as a filter on every query the
2882
+ * iframe makes. Centrali never interprets the bytes — treat it as
2883
+ * opaque (1-255 chars).
2884
+ */
2885
+ tenantId: string;
2886
+ /**
2887
+ * Defaults to `['events:read']`. Pass `['events:read', 'events:replay']`
2888
+ * to allow the iframe's "Replay" action. The issuing service account
2889
+ * must already hold the corresponding capability.
2890
+ */
2891
+ capabilities?: EmbedCapability[];
2892
+ /**
2893
+ * Optional cohort id. Useful if you want to revoke every token issued
2894
+ * for one of your end-users on logout — mint each with the same
2895
+ * `sessionId`, then call `revokeSession({ sessionId })` later. Server
2896
+ * mints a random one if omitted (returned in the response).
2897
+ */
2898
+ sessionId?: string;
2899
+ /**
2900
+ * Token TTL in seconds. Defaults to 600 (10 min). Capped at 3600 (1h)
2901
+ * server-side; out-of-range values 400.
2902
+ */
2903
+ ttlSeconds?: number;
2904
+ }
2905
+ interface IssueEmbedTokenResult {
2906
+ /** `ev_…` JWT for the iframe's URL fragment. */
2907
+ token: string;
2908
+ /** Echo of the input sessionId, or the server-minted one if omitted. */
2909
+ sessionId: string;
2910
+ /** ISO-8601 timestamp at which the token's `exp` claim fires. */
2911
+ expiresAt: string;
2912
+ }
2913
+ interface RevokeEmbedSessionInput {
2914
+ sessionId: string;
2915
+ }
2916
+ interface RevokeEmbedSessionResult {
2917
+ sessionId: string;
2918
+ revokedAt: string;
2919
+ }
2920
+
2805
2921
  /**
2806
2922
  * Internal configuration for realtime connections.
2807
2923
  */
@@ -5112,6 +5228,102 @@ declare class WebhookSubscriptionsManager {
5112
5228
  * capture it before closing the response.
5113
5229
  */
5114
5230
  rotateSecret(subscriptionId: string): Promise<ApiResponse<WebhookSubscription>>;
5231
+ /**
5232
+ * List the outbound payload versions a subscription can be pinned to via
5233
+ * `create`/`update`'s `payloadVersion`. Each version selects the shape its
5234
+ * deliveries are projected into; subscribers upgrade on their own timeline.
5235
+ *
5236
+ * @example
5237
+ * ```ts
5238
+ * const { data } = await centrali.webhookSubscriptions.getPayloadVersions();
5239
+ * console.log('Latest payload version:', data.latest);
5240
+ * ```
5241
+ */
5242
+ getPayloadVersions(): Promise<ApiResponse<WebhookPayloadVersions>>;
5243
+ }
5244
+
5245
+ /**
5246
+ * Embed manager — server-side helpers for the white-label Event Log iframe
5247
+ * (`embed.centrali.io/v1/event-log`, CEN-1301).
5248
+ *
5249
+ * Why this lives outside the main axios instance:
5250
+ * The shared client mints workspace JWTs with `resource=<data-service>`,
5251
+ * so its `aud` claim is the data plane. IAM's embed issuance endpoint
5252
+ * explicitly rejects data-audienced tokens (`audience_mismatch`) — see
5253
+ * services/backend/iam/src/controllers/embedTokenController.ts. This
5254
+ * manager keeps its own axios instance pointed at the IAM host and its
5255
+ * own cached IAM-audienced workspace JWT, minted via
5256
+ * `fetchIamAudiencedToken`.
5257
+ *
5258
+ * Confidential credentials only: IAM also rejects publishable keys and
5259
+ * service-account dev tokens. The manager throws up front if the SDK was
5260
+ * constructed without `clientId` + `clientSecret`.
5261
+ */
5262
+
5263
+ interface EmbedManagerOptions {
5264
+ baseUrl: string;
5265
+ workspaceId: string;
5266
+ clientId?: string;
5267
+ clientSecret?: string;
5268
+ /**
5269
+ * Pass-through of the SDK's `axiosConfig` (custom CA, agent, timeouts,
5270
+ * etc.). The manager always disables HTTP_PROXY/HTTPS_PROXY env vars
5271
+ * to match the main client + token mint, but caller-supplied fields
5272
+ * are merged on top — including an explicit `proxy` override.
5273
+ */
5274
+ axiosConfig?: AxiosRequestConfig;
5275
+ }
5276
+ /**
5277
+ * Server-side helpers for the Event Log embed iframe. Access via
5278
+ * `client.embed.eventLog`.
5279
+ *
5280
+ * @example
5281
+ * ```ts
5282
+ * const { token, sessionId, expiresAt } = await client.embed.eventLog.issueToken({
5283
+ * tenantId: customerOrgId,
5284
+ * capabilities: ['events:read', 'events:replay'],
5285
+ * ttlSeconds: 900,
5286
+ * });
5287
+ *
5288
+ * // Render in your frontend:
5289
+ * // <iframe src={`https://embed.centrali.io/v1/event-log#token=${token}&o=${origin}`} />
5290
+ *
5291
+ * // On user logout:
5292
+ * await client.embed.eventLog.revokeSession({ sessionId });
5293
+ * ```
5294
+ */
5295
+ declare class EmbedManager {
5296
+ private readonly _eventLog;
5297
+ constructor(opts: EmbedManagerOptions);
5298
+ get eventLog(): EventLogEmbed;
5299
+ }
5300
+ declare class EventLogEmbed {
5301
+ private readonly baseUrl;
5302
+ private readonly workspaceId;
5303
+ private readonly clientId?;
5304
+ private readonly clientSecret?;
5305
+ private readonly axios;
5306
+ /**
5307
+ * Cached IAM-audienced workspace JWT. Reused across calls; refreshed
5308
+ * lazily on 401 (which is what IAM returns when `exp` fires).
5309
+ */
5310
+ private iamToken;
5311
+ private inflightTokenMint;
5312
+ constructor(opts: EmbedManagerOptions);
5313
+ /**
5314
+ * Mint a short-lived `ev_…` embed token. Hand the result to your
5315
+ * frontend and drop it into the iframe URL fragment as `#token=…&o=…`.
5316
+ */
5317
+ issueToken(input: IssueEmbedTokenInput): Promise<IssueEmbedTokenResult>;
5318
+ /**
5319
+ * Revoke an embed session (typically tied to your user's logout).
5320
+ * Every embed token carrying this `sessionId` is rejected by
5321
+ * data-service until the entry expires (max token TTL).
5322
+ */
5323
+ revokeSession(input: RevokeEmbedSessionInput): Promise<RevokeEmbedSessionResult>;
5324
+ private serializeIssueBody;
5325
+ private postWithIamToken;
5326
+ private getIamToken;
5115
5327
  }
5116
5328
 
5117
5329
  /** Mirror of `@centrali/query`'s `ValidateOptions`. */
@@ -5237,6 +5449,7 @@ declare class CentraliSDK {
5237
5449
  private _files;
5238
5450
  private _webhookSubscriptions;
5239
5451
  private _query;
5452
+ private _embed;
5240
5453
  private isRefreshingToken;
5241
5454
  private tokenRefreshPromise;
5242
5455
  constructor(options: CentraliSDKOptions);
@@ -5674,6 +5887,17 @@ declare class CentraliSDK {
5674
5887
  * ```
5675
5888
  */
5676
5889
  get webhookSubscriptions(): WebhookSubscriptionsManager;
5890
+ /**
5891
+ * Server-side helpers for the white-label Event Log embed
5892
+ * (CEN-1301 — see `embed.centrali.io/v1/event-log`). Use to mint
5893
+ * short-lived tokens that scope the iframe to one of your end-user
5894
+ * tenants, and to revoke them on logout.
5895
+ *
5896
+ * Requires the SDK to be constructed with `clientId` + `clientSecret`
5897
+ * (service-account client credentials). Publishable keys and
5898
+ * supplied bearer tokens are rejected by IAM for this surface.
5899
+ */
5900
+ get embed(): EmbedManager;
5677
5901
  /**
5678
5902
  * Manually set or update the bearer token for subsequent requests.
5679
5903
  */
@@ -6058,4 +6282,4 @@ declare class CentraliSDK {
6058
6282
  checkAuthorization(options: CheckAuthorizationOptions): Promise<ApiResponse<AuthorizationResult>>;
6059
6283
  }
6060
6284
 
6061
- export { type AcceptSuggestionResult, type AddAllowedDomainOptions, type AllowedDomain, type AllowedDomainsListResponse, AllowedDomainsManager, type AnomalyAnalysisResult, type AnomalyDetectionData, type AnomalyEventType, type AnomalyInsight, type AnomalyInsightData, AnomalyInsightsManager, type ApiResponse, type ArrayPropertyDefinition, AuditLogManager, type AuthorizationResult, type BasePropertyDefinition, type BatchScanResult, type BatchScanStatus, type BooleanPropertyDefinition, type BulkOperationResult, CANONICAL_OPERATORS, type CanonicalOperator, CentraliError, CentraliSDK, type CentraliSDKOptions, type CheckAuthorizationOptions, CollectionsManager, type ComputeEventType, type ComputeFunction, ComputeFunctionsManager, type ComputeJobStatus, type ComputeJobStatusResponse, type ConditionOperator, type CreateComputeFunctionInput, type CreateOrchestrationInput, type CreateSmartQueryInput, type CreateStructureInput, type CreateTriggerInput, type CreateWebhookSubscriptionInput, type DateTimePropertyDefinition, type DateWindowOption, type DeleteRecordOptions, type EndpointResponse, type ExecuteSavedQueryValues, type ExecuteSmartQueryOptions, type ExpandOptions, type FieldCondition, type FieldConditionMap, type FileMetadata, FilesManager, type FilterOperators, type FilterValue, type FunctionMemoryUsage, type FunctionRun, type FunctionRunError, type FunctionRunExecutionSource, type FunctionRunStatus, FunctionRunsManager, type FunctionTrigger, type GetRecordOptions, type IncludeClause, type InsightSeverity, type InsightStatus, type InsightType, type InsightsSummary, type InvokeEndpointOptions, type InvokeTriggerOptions, JOINS_MAX_LENGTH, type JoinClause, type JoinType, type LegacyTranslateOptions, type LegacyTranslateResult, type LegacyTranslateWarning, type ListAllTriggersOptions, type ListCollectionsOptions, type ListComputeFunctionsOptions, type ListFunctionRunsOptions, type ListInsightsOptions, type ListOrchestrationRunsOptions, type ListOrchestrationsOptions, type ListSmartQueryOptions, type ListStructuresOptions, type ListValidationSuggestionsOptions, type ListWebhookDeliveriesOptions, type NumberPropertyDefinition, OPERATOR_METADATA, type ObjectPropertyDefinition, type OperatorMeta, type OperatorTypeApplicability, type OperatorValueShape, type Orchestration, type OrchestrationCaseEvaluation, type OrchestrationCondition, type OrchestrationConditionEvaluation, type OrchestrationDecisionCase, type OrchestrationDecisionResult, type OrchestrationDelayConfig, type OrchestrationEventType, type OrchestrationFailureReason, type OrchestrationOnFailure, type OrchestrationOnSuccess, type OrchestrationRetryConfig, type OrchestrationRun, type OrchestrationRunStatus, type OrchestrationRunStep, OrchestrationRunsManager, type OrchestrationScheduleType, type OrchestrationStatus, type OrchestrationStep, type OrchestrationStepError, type OrchestrationStepStatus, type OrchestrationStepType, type OrchestrationTrigger, type OrchestrationTriggerMetadata, type OrchestrationTriggerType, OrchestrationsManager, type PageClause, type PaginatedResponse, type ParsedUrlQuery, type PropertyDefinition, type PropertyType, type QueryDefinition, type QueryError, type QueryErrorCode, type QueryExecutionMode, type QueryHttpError, type QueryHttpErrorCode, QueryManager, type QueryRecordOptions, type QueryResult, type QueryResultMeta, type QueryValidateOptions, type QueryVariableDefinition, RECORDS_PAGE_DEFAULT_LIMIT, RECORDS_PAGE_MAX_LIMIT, type RealtimeAnomalyDetectionEvent, type RealtimeAnomalyInsightEvent, type RealtimeCloseEvent, type RealtimeError, type RealtimeEvent, type RealtimeEventType, type RealtimeFunctionRunEvent, RealtimeManager, type RealtimeOrchestrationRunEvent, type RealtimeRecordEvent, type RealtimeSubscribeOptions, type RealtimeSubscription, type RealtimeValidationBatchEvent, type RealtimeValidationSuggestionEvent, type RecordEventType, RecordEvents, type RecordTtlOptions, RecordsManager, type ReferencePropertyDefinition, type ResourceCategory, type SavedQueryDefinition, type SavedQueryScalarBinding, type ScalarValue, type SchemaDiscoveryMode, type SearchHit, type SearchOptions, type SearchResponse, type SelectClause, SmartQueriesManager, type SmartQuery, type SmartQueryDefinition, type SmartQueryExecuteResult, type SmartQueryFieldCondition, type SmartQueryJoin, type SmartQuerySort, type SmartQueryWhereClause, type SortClause, type StepEncryptedParam, type StringPropertyDefinition, type Structure, StructuresManager, type TestComputeFunctionInput, type TestComputeFunctionResult, type TestSmartQueryInput, type TextSearchClause, type TriggerExecutionType, type TriggerHealthMetrics, type TriggerHealthStatus, type TriggerInvokeResponse, type TriggerOrchestrationRunOptions, type TriggerScanOptions, type TriggerWithHealth, TriggersManager, type UpdateComputeFunctionInput, type UpdateOrchestrationInput, type UpdateSmartQueryInput, type UpdateStructureInput, type UpdateTriggerInput, type UpdateWebhookSubscriptionInput, type UrlParserOptions, type ValidateStructureInput, type ValidationBatchData, type ValidationEventType, type ValidationIssueType, ValidationManager, type ValidationResult, type ValidationSuggestion, type ValidationSuggestionData, type ValidationSuggestionStatus, type ValidationSummary, type VariableType, type WaitForScanOptions, type WebhookCancelResponse, type WebhookDeliveriesListMeta, type WebhookDelivery, type WebhookDeliveryStatus, type WebhookDeliverySummary, type WebhookReplayResponse, type WebhookSubscription, WebhookSubscriptionsManager, type WhereExpression, fetchClientToken, getAllowedDomainsApiPath, getAnomalyAnalysisTriggerApiPath, getAnomalyInsightAcknowledgeApiPath, getAnomalyInsightDismissApiPath, getAnomalyInsightsApiPath, getAnomalyInsightsBulkAcknowledgeApiPath, getAnomalyInsightsSummaryApiPath, getApiUrl, getAuthUrl, getCollectionBySlugApiPath, getCollectionInsightsApiPath, getCollectionValidateApiPath, getCollectionsApiPath, getComputeFunctionTestApiPath, getComputeFunctionsApiPath, getComputeJobStatusApiPath, getEndpointApiPath, getFileUploadApiPath, getFilesCanonicalApiPath, getFunctionRunsApiPath, getFunctionRunsByFunctionApiPath, getFunctionRunsByTriggerApiPath, getFunctionTriggerExecuteApiPath, getFunctionTriggerPauseApiPath, getFunctionTriggerResumeApiPath, getFunctionTriggersApiPath, getOrchestrationRunStepsApiPath, getOrchestrationRunsApiPath, getOrchestrationRunsCanonicalApiPath, getOrchestrationsApiPath, getRealtimeUrl, getRecordApiPath, getSavedQueryCanonicalByIdPath, getSavedQueryCanonicalCollectionPath, getSavedQueryCanonicalExecutePath, getSavedQueryCanonicalTestPath, getSearchApiPath, getSmartQueriesApiPath, getSmartQueriesStructureApiPath, getSmartQueryByNameApiPath, getSmartQueryExecuteApiPath, getSmartQueryTestApiPath, getStructureBySlugApiPath, getStructureInsightsApiPath, getStructureValidateApiPath, getStructuresApiPath, getValidationBulkAcceptApiPath, getValidationBulkRejectApiPath, getValidationPendingCountApiPath, getValidationRecordSuggestionsApiPath, getValidationScanApiPath, getValidationSuggestionAcceptApiPath, getValidationSuggestionRejectApiPath, getValidationSuggestionsApiPath, getValidationSummaryApiPath, getWebhookDeliveryCancelApiPath, getWebhookDeliveryRetryApiPath, getWebhookSubscriptionDeliveriesApiPath, getWebhookSubscriptionRotateSecretApiPath, getWebhookSubscriptionsApiPath, isCentraliError, operatorsForFieldType };
6285
+ export { type AcceptSuggestionResult, type AddAllowedDomainOptions, type AllowedDomain, type AllowedDomainsListResponse, AllowedDomainsManager, type AnomalyAnalysisResult, type AnomalyDetectionData, type AnomalyEventType, type AnomalyInsight, type AnomalyInsightData, AnomalyInsightsManager, type ApiResponse, type ArrayPropertyDefinition, AuditLogManager, type AuthorizationResult, type BasePropertyDefinition, type BatchScanResult, type BatchScanStatus, type BooleanPropertyDefinition, type BulkOperationResult, CANONICAL_OPERATORS, type CanonicalOperator, CentraliError, CentraliSDK, type CentraliSDKOptions, type CheckAuthorizationOptions, CollectionsManager, type ComputeEventType, type ComputeFunction, ComputeFunctionsManager, type ComputeJobStatus, type ComputeJobStatusResponse, type ConditionOperator, type CreateComputeFunctionInput, type CreateOrchestrationInput, type CreateSmartQueryInput, type CreateStructureInput, type CreateTriggerInput, type CreateWebhookSubscriptionInput, type DateTimePropertyDefinition, type DateWindowOption, type DeleteRecordOptions, type EmbedCapability, EmbedManager, type EndpointResponse, EventLogEmbed, type ExecuteSavedQueryValues, type ExecuteSmartQueryOptions, type ExpandOptions, type FieldCondition, type FieldConditionMap, type FileMetadata, FilesManager, type FilterOperators, type FilterValue, type FunctionMemoryUsage, type FunctionRun, type FunctionRunError, type FunctionRunExecutionSource, type FunctionRunStatus, FunctionRunsManager, type FunctionTrigger, type GetRecordOptions, type IncludeClause, type InsightSeverity, type InsightStatus, type InsightType, type InsightsSummary, type InvokeEndpointOptions, type InvokeTriggerOptions, type IssueEmbedTokenInput, type IssueEmbedTokenResult, JOINS_MAX_LENGTH, type JoinClause, type JoinType, type LegacyTranslateOptions, type LegacyTranslateResult, type LegacyTranslateWarning, type ListAllTriggersOptions, type ListCollectionsOptions, type ListComputeFunctionsOptions, type ListFunctionRunsOptions, type ListInsightsOptions, type ListOrchestrationRunsOptions, type ListOrchestrationsOptions, type ListSmartQueryOptions, type ListStructuresOptions, type ListValidationSuggestionsOptions, type ListWebhookDeliveriesOptions, type NumberPropertyDefinition, OPERATOR_METADATA, type ObjectPropertyDefinition, type OperatorMeta, type OperatorTypeApplicability, type OperatorValueShape, type Orchestration, type OrchestrationCaseEvaluation, type OrchestrationCondition, type OrchestrationConditionEvaluation, type OrchestrationDecisionCase, type OrchestrationDecisionResult, type OrchestrationDelayConfig, type OrchestrationEventType, type OrchestrationFailureReason, type OrchestrationOnFailure, type OrchestrationOnSuccess, type OrchestrationRetryConfig, type OrchestrationRun, type OrchestrationRunStatus, type OrchestrationRunStep, OrchestrationRunsManager, type OrchestrationScheduleType, type OrchestrationStatus, type OrchestrationStep, type OrchestrationStepError, type OrchestrationStepStatus, type OrchestrationStepType, type OrchestrationTrigger, type OrchestrationTriggerMetadata, type OrchestrationTriggerType, OrchestrationsManager, type PageClause, type PaginatedResponse, type ParsedUrlQuery, type PropertyDefinition, type PropertyType, type QueryDefinition, type QueryError, type QueryErrorCode, type QueryExecutionMode, type QueryHttpError, type QueryHttpErrorCode, QueryManager, type QueryRecordOptions, type QueryResult, type QueryResultMeta, type QueryValidateOptions, type QueryVariableDefinition, RECORDS_PAGE_DEFAULT_LIMIT, RECORDS_PAGE_MAX_LIMIT, type RealtimeAnomalyDetectionEvent, type RealtimeAnomalyInsightEvent, type RealtimeCloseEvent, type RealtimeError, type RealtimeEvent, type RealtimeEventType, type RealtimeFunctionRunEvent, RealtimeManager, type RealtimeOrchestrationRunEvent, type RealtimeRecordEvent, type RealtimeSubscribeOptions, type RealtimeSubscription, type RealtimeValidationBatchEvent, type RealtimeValidationSuggestionEvent, type RecordEventType, RecordEvents, type RecordTtlOptions, RecordsManager, type ReferencePropertyDefinition, type ResourceCategory, type RevokeEmbedSessionInput, type RevokeEmbedSessionResult, type SavedQueryDefinition, type SavedQueryScalarBinding, type ScalarValue, type SchemaDiscoveryMode, type SearchHit, type SearchOptions, type SearchResponse, type SelectClause, SmartQueriesManager, type SmartQuery, type SmartQueryDefinition, type SmartQueryExecuteResult, type SmartQueryFieldCondition, type SmartQueryJoin, type SmartQuerySort, type SmartQueryWhereClause, type SortClause, type StepEncryptedParam, type StringPropertyDefinition, type Structure, StructuresManager, type TestComputeFunctionInput, type TestComputeFunctionResult, type TestSmartQueryInput, type TextSearchClause, type TriggerExecutionType, type TriggerHealthMetrics, type TriggerHealthStatus, type TriggerInvokeResponse, type TriggerOrchestrationRunOptions, type TriggerScanOptions, type TriggerWithHealth, TriggersManager, type UpdateComputeFunctionInput, type UpdateOrchestrationInput, type UpdateSmartQueryInput, type UpdateStructureInput, type UpdateTriggerInput, type UpdateWebhookSubscriptionInput, type UrlParserOptions, type ValidateStructureInput, type ValidationBatchData, type ValidationEventType, type ValidationIssueType, ValidationManager, type ValidationResult, type ValidationSuggestion, type ValidationSuggestionData, type ValidationSuggestionStatus, type ValidationSummary, type VariableType, type WaitForScanOptions, type WebhookCancelResponse, type WebhookDeliveriesListMeta, type WebhookDelivery, type WebhookDeliveryStatus, type WebhookDeliverySummary, type WebhookPayloadVersions, type WebhookReplayResponse, type WebhookSubscription, WebhookSubscriptionsManager, type WhereExpression, fetchClientToken, getAllowedDomainsApiPath, getAnomalyAnalysisTriggerApiPath, getAnomalyInsightAcknowledgeApiPath, getAnomalyInsightDismissApiPath, getAnomalyInsightsApiPath, getAnomalyInsightsBulkAcknowledgeApiPath, getAnomalyInsightsSummaryApiPath, getApiUrl, getAuthUrl, getCollectionBySlugApiPath, getCollectionInsightsApiPath, getCollectionValidateApiPath, getCollectionsApiPath, getComputeFunctionTestApiPath, getComputeFunctionsApiPath, getComputeJobStatusApiPath, getEndpointApiPath, getFileUploadApiPath, getFilesCanonicalApiPath, getFunctionRunsApiPath, getFunctionRunsByFunctionApiPath, getFunctionRunsByTriggerApiPath, getFunctionTriggerExecuteApiPath, getFunctionTriggerPauseApiPath, getFunctionTriggerResumeApiPath, getFunctionTriggersApiPath, getOrchestrationRunStepsApiPath, getOrchestrationRunsApiPath, getOrchestrationRunsCanonicalApiPath, getOrchestrationsApiPath, getRealtimeUrl, getRecordApiPath, getSavedQueryCanonicalByIdPath, getSavedQueryCanonicalCollectionPath, getSavedQueryCanonicalExecutePath, getSavedQueryCanonicalTestPath, getSearchApiPath, getSmartQueriesApiPath, getSmartQueriesStructureApiPath, getSmartQueryByNameApiPath, getSmartQueryExecuteApiPath, getSmartQueryTestApiPath, getStructureBySlugApiPath, getStructureInsightsApiPath, getStructureValidateApiPath, getStructuresApiPath, getValidationBulkAcceptApiPath, getValidationBulkRejectApiPath, getValidationPendingCountApiPath, getValidationRecordSuggestionsApiPath, getValidationScanApiPath, getValidationSuggestionAcceptApiPath, getValidationSuggestionRejectApiPath, getValidationSuggestionsApiPath, getValidationSummaryApiPath, getWebhookDeliveryCancelApiPath, getWebhookDeliveryRetryApiPath, getWebhookPayloadVersionsApiPath, getWebhookSubscriptionDeliveriesApiPath, getWebhookSubscriptionRotateSecretApiPath, getWebhookSubscriptionsApiPath, isCentraliError, operatorsForFieldType };
package/dist/index.js CHANGED
@@ -75,6 +75,8 @@ __export(index_exports, {
75
75
  CentraliSDK: () => CentraliSDK,
76
76
  CollectionsManager: () => CollectionsManager,
77
77
  ComputeFunctionsManager: () => ComputeFunctionsManager,
78
+ EmbedManager: () => EmbedManager,
79
+ EventLogEmbed: () => EventLogEmbed,
78
80
  FilesManager: () => FilesManager,
79
81
  FunctionRunsManager: () => FunctionRunsManager,
80
82
  JOINS_MAX_LENGTH: () => JOINS_MAX_LENGTH,
@@ -150,6 +152,7 @@ __export(index_exports, {
150
152
  getValidationSummaryApiPath: () => getValidationSummaryApiPath,
151
153
  getWebhookDeliveryCancelApiPath: () => getWebhookDeliveryCancelApiPath,
152
154
  getWebhookDeliveryRetryApiPath: () => getWebhookDeliveryRetryApiPath,
155
+ getWebhookPayloadVersionsApiPath: () => getWebhookPayloadVersionsApiPath,
153
156
  getWebhookSubscriptionDeliveriesApiPath: () => getWebhookSubscriptionDeliveriesApiPath,
154
157
  getWebhookSubscriptionRotateSecretApiPath: () => getWebhookSubscriptionRotateSecretApiPath,
155
158
  getWebhookSubscriptionsApiPath: () => getWebhookSubscriptionsApiPath,
@@ -385,6 +388,9 @@ function getWebhookSubscriptionsApiPath(workspaceId, subscriptionId) {
385
388
  const basePath = `data/workspace/${workspaceId}/api/v1/webhook-subscriptions`;
386
389
  return subscriptionId ? `${basePath}/${subscriptionId}` : basePath;
387
390
  }
391
+ function getWebhookPayloadVersionsApiPath(workspaceId) {
392
+ return `data/workspace/${workspaceId}/api/v1/webhook-subscriptions/payload-versions`;
393
+ }
388
394
  function getWebhookSubscriptionRotateSecretApiPath(workspaceId, subscriptionId) {
389
395
  return `data/workspace/${workspaceId}/api/v1/webhook-subscriptions/${subscriptionId}/rotate-secret`;
390
396
  }
@@ -406,14 +412,25 @@ function encodeFormData(data) {
406
412
  }
407
413
  function fetchClientToken(clientId, clientSecret, baseUrl) {
408
414
  return __async(this, null, function* () {
409
- const authUrl = getAuthUrl(baseUrl);
410
415
  const apiUrl = getApiUrl(baseUrl);
416
+ return fetchClientTokenForResource(clientId, clientSecret, baseUrl, `${apiUrl}/data`);
417
+ });
418
+ }
419
+ function fetchIamAudiencedToken(clientId, clientSecret, baseUrl) {
420
+ return __async(this, null, function* () {
421
+ const authUrl = getAuthUrl(baseUrl);
422
+ return fetchClientTokenForResource(clientId, clientSecret, baseUrl, authUrl);
423
+ });
424
+ }
425
+ function fetchClientTokenForResource(clientId, clientSecret, baseUrl, resource) {
426
+ return __async(this, null, function* () {
427
+ const authUrl = getAuthUrl(baseUrl);
411
428
  const tokenEndpoint = `${authUrl}/token`;
412
429
  const form = encodeFormData({
413
430
  grant_type: "client_credentials",
414
431
  client_id: clientId,
415
432
  client_secret: clientSecret,
416
- resource: `${apiUrl}/data`
433
+ resource
417
434
  });
418
435
  const resp = yield import_axios2.default.post(
419
436
  tokenEndpoint,
@@ -7999,10 +8016,128 @@ var WebhookSubscriptionsManager = class {
7999
8016
  const path = getWebhookSubscriptionRotateSecretApiPath(this.workspaceId, subscriptionId);
8000
8017
  return this.requestFn("POST", path);
8001
8018
  }
8019
+ /**
8020
+ * List the outbound payload versions a subscription can be pinned to via
8021
+ * `create`/`update`'s `payloadVersion`. Each version selects the shape its
8022
+ * deliveries are projected into; subscribers upgrade on their own timeline.
8023
+ *
8024
+ * @example
8025
+ * ```ts
8026
+ * const { data } = await centrali.webhookSubscriptions.getPayloadVersions();
8027
+ * console.log('Latest payload version:', data.latest);
8028
+ * ```
8029
+ */
8030
+ getPayloadVersions() {
8031
+ const path = getWebhookPayloadVersionsApiPath(this.workspaceId);
8032
+ return this.requestFn("GET", path);
8033
+ }
8002
8034
  };
8003
8035
 
8004
- // src/client.ts
8036
+ // src/managers/embed.ts
8005
8037
  var import_axios3 = __toESM(require("axios"));
8038
+ var EmbedManager = class {
8039
+ constructor(opts) {
8040
+ this._eventLog = new EventLogEmbed(opts);
8041
+ }
8042
+ get eventLog() {
8043
+ return this._eventLog;
8044
+ }
8045
+ };
8046
+ var EventLogEmbed = class {
8047
+ constructor(opts) {
8048
+ /**
8049
+ * Cached IAM-audienced workspace JWT. Reused across calls; refreshed
8050
+ * lazily on 401 (which is what IAM returns when `exp` fires).
8051
+ */
8052
+ this.iamToken = null;
8053
+ this.inflightTokenMint = null;
8054
+ this.baseUrl = opts.baseUrl;
8055
+ this.workspaceId = opts.workspaceId;
8056
+ this.clientId = opts.clientId;
8057
+ this.clientSecret = opts.clientSecret;
8058
+ this.axios = import_axios3.default.create(__spreadValues({
8059
+ baseURL: getAuthUrl(opts.baseUrl),
8060
+ headers: { "Content-Type": "application/json" },
8061
+ proxy: false
8062
+ }, opts.axiosConfig));
8063
+ }
8064
+ /**
8065
+ * Mint a short-lived `ev_…` embed token. Hand the result to your
8066
+ * frontend and drop it into the iframe URL fragment as `#token=…&o=…`.
8067
+ */
8068
+ issueToken(input) {
8069
+ return __async(this, null, function* () {
8070
+ const path = `/workspace/${this.workspaceId}/embed/event-log/issue-token`;
8071
+ return this.postWithIamToken(path, this.serializeIssueBody(input));
8072
+ });
8073
+ }
8074
+ /**
8075
+ * Revoke an embed session (typically tied to your user's logout).
8076
+ * Every embed token carrying this `sessionId` is rejected by
8077
+ * data-service until the entry expires (max token TTL).
8078
+ */
8079
+ revokeSession(input) {
8080
+ return __async(this, null, function* () {
8081
+ const path = `/workspace/${this.workspaceId}/embed/event-log/revoke-session`;
8082
+ return this.postWithIamToken(path, { sessionId: input.sessionId });
8083
+ });
8084
+ }
8085
+ serializeIssueBody(input) {
8086
+ const body = { tenantId: input.tenantId };
8087
+ if (input.capabilities) body.capabilities = input.capabilities;
8088
+ if (input.sessionId) body.sessionId = input.sessionId;
8089
+ if (input.ttlSeconds !== void 0) body.ttlSeconds = input.ttlSeconds;
8090
+ return body;
8091
+ }
8092
+ postWithIamToken(path, body) {
8093
+ return __async(this, null, function* () {
8094
+ var _a;
8095
+ const token = yield this.getIamToken();
8096
+ try {
8097
+ const resp = yield this.axios.post(path, body, {
8098
+ headers: { Authorization: `Bearer ${token}` }
8099
+ });
8100
+ return resp.data;
8101
+ } catch (err) {
8102
+ const status = (_a = err == null ? void 0 : err.response) == null ? void 0 : _a.status;
8103
+ if (status === 401) {
8104
+ this.iamToken = null;
8105
+ const fresh = yield this.getIamToken();
8106
+ const resp = yield this.axios.post(path, body, {
8107
+ headers: { Authorization: `Bearer ${fresh}` }
8108
+ });
8109
+ return resp.data;
8110
+ }
8111
+ throw err;
8112
+ }
8113
+ });
8114
+ }
8115
+ getIamToken() {
8116
+ return __async(this, null, function* () {
8117
+ if (this.iamToken) return this.iamToken;
8118
+ if (this.inflightTokenMint) return this.inflightTokenMint;
8119
+ if (!this.clientId || !this.clientSecret) {
8120
+ throw new Error(
8121
+ "Embed token issuance requires the SDK to be configured with clientId + clientSecret (service-account client credentials). Publishable keys and supplied bearer tokens are not accepted by IAM for this endpoint."
8122
+ );
8123
+ }
8124
+ this.inflightTokenMint = fetchIamAudiencedToken(
8125
+ this.clientId,
8126
+ this.clientSecret,
8127
+ this.baseUrl
8128
+ );
8129
+ try {
8130
+ this.iamToken = yield this.inflightTokenMint;
8131
+ return this.iamToken;
8132
+ } finally {
8133
+ this.inflightTokenMint = null;
8134
+ }
8135
+ });
8136
+ }
8137
+ };
8138
+
8139
+ // src/client.ts
8140
+ var import_axios4 = __toESM(require("axios"));
8006
8141
  var import_qs = __toESM(require("qs"));
8007
8142
 
8008
8143
  // src/internal/queryGuard.ts
@@ -8032,6 +8167,7 @@ var CentraliSDK = class {
8032
8167
  this._files = null;
8033
8168
  this._webhookSubscriptions = null;
8034
8169
  this._query = null;
8170
+ this._embed = null;
8035
8171
  this.isRefreshingToken = false;
8036
8172
  this.tokenRefreshPromise = null;
8037
8173
  this.options = options;
@@ -8048,7 +8184,7 @@ var CentraliSDK = class {
8048
8184
  throw new Error("Cannot use getToken with clientId/clientSecret. Use one auth method.");
8049
8185
  }
8050
8186
  const apiUrl = getApiUrl(options.baseUrl);
8051
- this.axios = import_axios3.default.create(__spreadValues({
8187
+ this.axios = import_axios4.default.create(__spreadValues({
8052
8188
  baseURL: apiUrl,
8053
8189
  paramsSerializer: (params) => import_qs.default.stringify(params, { arrayFormat: "repeat" }),
8054
8190
  proxy: false
@@ -8731,6 +8867,28 @@ var CentraliSDK = class {
8731
8867
  }
8732
8868
  return this._webhookSubscriptions;
8733
8869
  }
8870
+ /**
8871
+ * Server-side helpers for the white-label Event Log embed
8872
+ * (CEN-1301 — see `embed.centrali.io/v1/event-log`). Use to mint
8873
+ * short-lived tokens that scope the iframe to one of your end-user
8874
+ * tenants, and to revoke them on logout.
8875
+ *
8876
+ * Requires the SDK to be constructed with `clientId` + `clientSecret`
8877
+ * (service-account client credentials). Publishable keys and
8878
+ * supplied bearer tokens are rejected by IAM for this surface.
8879
+ */
8880
+ get embed() {
8881
+ if (!this._embed) {
8882
+ this._embed = new EmbedManager({
8883
+ baseUrl: this.options.baseUrl,
8884
+ workspaceId: this.options.workspaceId,
8885
+ clientId: this.options.clientId,
8886
+ clientSecret: this.options.clientSecret,
8887
+ axiosConfig: this.options.axiosConfig
8888
+ });
8889
+ }
8890
+ return this._embed;
8891
+ }
8734
8892
  /**
8735
8893
  * Manually set or update the bearer token for subsequent requests.
8736
8894
  */
@@ -9240,6 +9398,8 @@ var CentraliSDK = class {
9240
9398
  CentraliSDK,
9241
9399
  CollectionsManager,
9242
9400
  ComputeFunctionsManager,
9401
+ EmbedManager,
9402
+ EventLogEmbed,
9243
9403
  FilesManager,
9244
9404
  FunctionRunsManager,
9245
9405
  JOINS_MAX_LENGTH,
@@ -9315,6 +9475,7 @@ var CentraliSDK = class {
9315
9475
  getValidationSummaryApiPath,
9316
9476
  getWebhookDeliveryCancelApiPath,
9317
9477
  getWebhookDeliveryRetryApiPath,
9478
+ getWebhookPayloadVersionsApiPath,
9318
9479
  getWebhookSubscriptionDeliveriesApiPath,
9319
9480
  getWebhookSubscriptionRotateSecretApiPath,
9320
9481
  getWebhookSubscriptionsApiPath,
package/index.ts CHANGED
@@ -32,6 +32,7 @@ export * from './src/types/insights';
32
32
  export * from './src/types/validation';
33
33
  export * from './src/types/webhooks';
34
34
  export * from './src/types/allowedDomains';
35
+ export * from './src/types/embed';
35
36
 
36
37
  // Realtime
37
38
  export { RealtimeManager } from './src/realtime/manager';
@@ -52,6 +53,7 @@ export { FunctionRunsManager } from './src/managers/functionRuns';
52
53
  export { OrchestrationRunsManager } from './src/managers/orchestrationRuns';
53
54
  export { FilesManager, FileMetadata } from './src/managers/files';
54
55
  export { WebhookSubscriptionsManager } from './src/managers/webhookSubscriptions';
56
+ export { EmbedManager, EventLogEmbed } from './src/managers/embed';
55
57
  export {
56
58
  QueryManager,
57
59
  type QueryValidateOptions,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@centrali-io/centrali-sdk",
3
- "version": "6.6.0",
3
+ "version": "6.8.0",
4
4
  "description": "Centrali Node SDK",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/client.ts CHANGED
@@ -36,6 +36,7 @@ import { OrchestrationRunsManager } from './managers/orchestrationRuns';
36
36
  import { FilesManager } from './managers/files';
37
37
  import { WebhookSubscriptionsManager } from './managers/webhookSubscriptions';
38
38
  import { QueryManager } from './managers/query';
39
+ import { EmbedManager } from './managers/embed';
39
40
 
40
41
  export class CentraliSDK {
41
42
  private axios: AxiosInstance;
@@ -59,6 +60,7 @@ export class CentraliSDK {
59
60
  private _files: FilesManager | null = null;
60
61
  private _webhookSubscriptions: WebhookSubscriptionsManager | null = null;
61
62
  private _query: QueryManager | null = null;
63
+ private _embed: EmbedManager | null = null;
62
64
  private isRefreshingToken: boolean = false;
63
65
  private tokenRefreshPromise: Promise<string> | null = null;
64
66
 
@@ -814,6 +816,29 @@ export class CentraliSDK {
814
816
  return this._webhookSubscriptions;
815
817
  }
816
818
 
819
+ /**
820
+ * Server-side helpers for the white-label Event Log embed
821
+ * (CEN-1301 — see `embed.centrali.io/v1/event-log`). Use to mint
822
+ * short-lived tokens that scope the iframe to one of your end-user
823
+ * tenants, and to revoke them on logout.
824
+ *
825
+ * Requires the SDK to be constructed with `clientId` + `clientSecret`
826
+ * (service-account client credentials). Publishable keys and
827
+ * supplied bearer tokens are rejected by IAM for this surface.
828
+ */
829
+ public get embed(): EmbedManager {
830
+ if (!this._embed) {
831
+ this._embed = new EmbedManager({
832
+ baseUrl: this.options.baseUrl,
833
+ workspaceId: this.options.workspaceId,
834
+ clientId: this.options.clientId,
835
+ clientSecret: this.options.clientSecret,
836
+ axiosConfig: this.options.axiosConfig,
837
+ });
838
+ }
839
+ return this._embed;
840
+ }
841
+
817
842
  /**
818
843
  * Manually set or update the bearer token for subsequent requests.
819
844
  */
@@ -14,14 +14,37 @@ export async function fetchClientToken(
14
14
  clientSecret: string,
15
15
  baseUrl: string
16
16
  ): Promise<string> {
17
- const authUrl = getAuthUrl(baseUrl);
18
17
  const apiUrl = getApiUrl(baseUrl);
18
+ return fetchClientTokenForResource(clientId, clientSecret, baseUrl, `${apiUrl}/data`);
19
+ }
20
+
21
+ /**
22
+ * Mint an IAM-audienced workspace JWT. Required for the embed-token issuance
23
+ * endpoint, which rejects data-audienced tokens with `audience_mismatch`
24
+ * (see services/backend/iam/src/controllers/embedTokenController.ts).
25
+ */
26
+ export async function fetchIamAudiencedToken(
27
+ clientId: string,
28
+ clientSecret: string,
29
+ baseUrl: string
30
+ ): Promise<string> {
31
+ const authUrl = getAuthUrl(baseUrl);
32
+ return fetchClientTokenForResource(clientId, clientSecret, baseUrl, authUrl);
33
+ }
34
+
35
+ async function fetchClientTokenForResource(
36
+ clientId: string,
37
+ clientSecret: string,
38
+ baseUrl: string,
39
+ resource: string
40
+ ): Promise<string> {
41
+ const authUrl = getAuthUrl(baseUrl);
19
42
  const tokenEndpoint = `${authUrl}/token`;
20
43
  const form = encodeFormData({
21
44
  grant_type: 'client_credentials',
22
45
  client_id: clientId,
23
46
  client_secret: clientSecret,
24
- resource: `${apiUrl}/data`
47
+ resource,
25
48
  });
26
49
  const resp = await axios.post(
27
50
  tokenEndpoint,
@@ -424,6 +424,14 @@ export function getWebhookSubscriptionsApiPath(workspaceId: string, subscription
424
424
  return subscriptionId ? `${basePath}/${subscriptionId}` : basePath;
425
425
  }
426
426
 
427
+ /**
428
+ * Generate the payload-versions API URL PATH. Lists the outbound payload
429
+ * versions a subscription can be pinned to.
430
+ */
431
+ export function getWebhookPayloadVersionsApiPath(workspaceId: string): string {
432
+ return `data/workspace/${workspaceId}/api/v1/webhook-subscriptions/payload-versions`;
433
+ }
434
+
427
435
  /**
428
436
  * Generate rotate-secret API URL PATH for a webhook subscription.
429
437
  */
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Embed manager — server-side helpers for the white-label Event Log iframe
3
+ * (`embed.centrali.io/v1/event-log`, CEN-1301).
4
+ *
5
+ * Why this lives outside the main axios instance:
6
+ * The shared client mints workspace JWTs with `resource=<data-service>`,
7
+ * so its `aud` claim is the data plane. IAM's embed issuance endpoint
8
+ * explicitly rejects data-audienced tokens (`audience_mismatch`) — see
9
+ * services/backend/iam/src/controllers/embedTokenController.ts. This
10
+ * manager keeps its own axios instance pointed at the IAM host and its
11
+ * own cached IAM-audienced workspace JWT, minted via
12
+ * `fetchIamAudiencedToken`.
13
+ *
14
+ * Confidential credentials only: IAM also rejects publishable keys and
15
+ * service-account dev tokens. The manager throws up front if the SDK was
16
+ * constructed without `clientId` + `clientSecret`.
17
+ */
18
+ import axios, { AxiosError, AxiosInstance, AxiosRequestConfig } from 'axios';
19
+
20
+ import { fetchIamAudiencedToken } from '../internal/auth';
21
+ import { getAuthUrl } from '../urls';
22
+ import type {
23
+ IssueEmbedTokenInput,
24
+ IssueEmbedTokenResult,
25
+ RevokeEmbedSessionInput,
26
+ RevokeEmbedSessionResult,
27
+ } from '../types/embed';
28
+
29
+ interface EmbedManagerOptions {
30
+ baseUrl: string;
31
+ workspaceId: string;
32
+ clientId?: string;
33
+ clientSecret?: string;
34
+ /**
35
+ * Pass-through of the SDK's `axiosConfig` (custom CA, agent, timeouts,
36
+ * etc.). The manager always disables HTTP_PROXY/HTTPS_PROXY env vars
37
+ * to match the main client + token mint, but caller-supplied fields
38
+ * are merged on top — including an explicit `proxy` override.
39
+ */
40
+ axiosConfig?: AxiosRequestConfig;
41
+ }
42
+
43
+ /**
44
+ * Server-side helpers for the Event Log embed iframe. Access via
45
+ * `client.embed.eventLog`.
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const { token, sessionId, expiresAt } = await client.embed.eventLog.issueToken({
50
+ * tenantId: customerOrgId,
51
+ * capabilities: ['events:read', 'events:replay'],
52
+ * ttlSeconds: 900,
53
+ * });
54
+ *
55
+ * // Render in your frontend:
56
+ * // <iframe src={`https://embed.centrali.io/v1/event-log#token=${token}&o=${origin}`} />
57
+ *
58
+ * // On user logout:
59
+ * await client.embed.eventLog.revokeSession({ sessionId });
60
+ * ```
61
+ */
62
+ export class EmbedManager {
63
+ private readonly _eventLog: EventLogEmbed;
64
+
65
+ constructor(opts: EmbedManagerOptions) {
66
+ this._eventLog = new EventLogEmbed(opts);
67
+ }
68
+
69
+ public get eventLog(): EventLogEmbed {
70
+ return this._eventLog;
71
+ }
72
+ }
73
+
74
+ export class EventLogEmbed {
75
+ private readonly baseUrl: string;
76
+ private readonly workspaceId: string;
77
+ private readonly clientId?: string;
78
+ private readonly clientSecret?: string;
79
+ private readonly axios: AxiosInstance;
80
+
81
+ /**
82
+ * Cached IAM-audienced workspace JWT. Reused across calls; refreshed
83
+ * lazily on 401 (which is what IAM returns when `exp` fires).
84
+ */
85
+ private iamToken: string | null = null;
86
+ private inflightTokenMint: Promise<string> | null = null;
87
+
88
+ constructor(opts: EmbedManagerOptions) {
89
+ this.baseUrl = opts.baseUrl;
90
+ this.workspaceId = opts.workspaceId;
91
+ this.clientId = opts.clientId;
92
+ this.clientSecret = opts.clientSecret;
93
+ // Mirror the main client + `fetchClientToken`: disable HTTP_PROXY/
94
+ // HTTPS_PROXY env-var pickup by default so embed-token traffic doesn't
95
+ // get silently routed through an outbound proxy a caller hasn't
96
+ // opted into. Caller-supplied `axiosConfig` (custom CA, agent,
97
+ // timeouts, explicit `proxy`) is merged on top.
98
+ this.axios = axios.create({
99
+ baseURL: getAuthUrl(opts.baseUrl),
100
+ headers: { 'Content-Type': 'application/json' },
101
+ proxy: false,
102
+ ...opts.axiosConfig,
103
+ });
104
+ }
105
+
106
+ /**
107
+ * Mint a short-lived `ev_…` embed token. Hand the result to your
108
+ * frontend and drop it into the iframe URL fragment as `#token=…&o=…`.
109
+ */
110
+ public async issueToken(input: IssueEmbedTokenInput): Promise<IssueEmbedTokenResult> {
111
+ const path = `/workspace/${this.workspaceId}/embed/event-log/issue-token`;
112
+ return this.postWithIamToken<IssueEmbedTokenResult>(path, this.serializeIssueBody(input));
113
+ }
114
+
115
+ /**
116
+ * Revoke an embed session (typically tied to your user's logout).
117
+ * Every embed token carrying this `sessionId` is rejected by
118
+ * data-service until the entry expires (max token TTL).
119
+ */
120
+ public async revokeSession(input: RevokeEmbedSessionInput): Promise<RevokeEmbedSessionResult> {
121
+ const path = `/workspace/${this.workspaceId}/embed/event-log/revoke-session`;
122
+ return this.postWithIamToken<RevokeEmbedSessionResult>(path, { sessionId: input.sessionId });
123
+ }
124
+
125
+ private serializeIssueBody(input: IssueEmbedTokenInput): Record<string, unknown> {
126
+ const body: Record<string, unknown> = { tenantId: input.tenantId };
127
+ if (input.capabilities) body.capabilities = input.capabilities;
128
+ if (input.sessionId) body.sessionId = input.sessionId;
129
+ if (input.ttlSeconds !== undefined) body.ttlSeconds = input.ttlSeconds;
130
+ return body;
131
+ }
132
+
133
+ private async postWithIamToken<T>(path: string, body: Record<string, unknown>): Promise<T> {
134
+ const token = await this.getIamToken();
135
+ try {
136
+ const resp = await this.axios.post<T>(path, body, {
137
+ headers: { Authorization: `Bearer ${token}` },
138
+ });
139
+ return resp.data;
140
+ } catch (err) {
141
+ // Refresh-on-401 once. Any subsequent 401 is propagated so the
142
+ // caller sees the real reason (missing capability, revoked SA,
143
+ // misconfigured audience, etc.) instead of a silent loop.
144
+ const status = (err as AxiosError)?.response?.status;
145
+ if (status === 401) {
146
+ this.iamToken = null;
147
+ const fresh = await this.getIamToken();
148
+ const resp = await this.axios.post<T>(path, body, {
149
+ headers: { Authorization: `Bearer ${fresh}` },
150
+ });
151
+ return resp.data;
152
+ }
153
+ throw err;
154
+ }
155
+ }
156
+
157
+ private async getIamToken(): Promise<string> {
158
+ if (this.iamToken) return this.iamToken;
159
+ if (this.inflightTokenMint) return this.inflightTokenMint;
160
+ if (!this.clientId || !this.clientSecret) {
161
+ throw new Error(
162
+ 'Embed token issuance requires the SDK to be configured with ' +
163
+ 'clientId + clientSecret (service-account client credentials). ' +
164
+ 'Publishable keys and supplied bearer tokens are not accepted by ' +
165
+ 'IAM for this endpoint.',
166
+ );
167
+ }
168
+ this.inflightTokenMint = fetchIamAudiencedToken(
169
+ this.clientId,
170
+ this.clientSecret,
171
+ this.baseUrl,
172
+ );
173
+ try {
174
+ this.iamToken = await this.inflightTokenMint;
175
+ return this.iamToken;
176
+ } finally {
177
+ this.inflightTokenMint = null;
178
+ }
179
+ }
180
+ }
@@ -11,12 +11,14 @@ import type {
11
11
  WebhookDeliveriesListMeta,
12
12
  WebhookReplayResponse,
13
13
  WebhookCancelResponse,
14
+ WebhookPayloadVersions,
14
15
  CreateWebhookSubscriptionInput,
15
16
  UpdateWebhookSubscriptionInput,
16
17
  ListWebhookDeliveriesOptions,
17
18
  } from '../types/webhooks';
18
19
  import {
19
20
  getWebhookSubscriptionsApiPath,
21
+ getWebhookPayloadVersionsApiPath,
20
22
  getWebhookSubscriptionRotateSecretApiPath,
21
23
  getWebhookSubscriptionDeliveriesApiPath,
22
24
  getWebhookDeliveryRetryApiPath,
@@ -203,4 +205,20 @@ export class WebhookSubscriptionsManager {
203
205
  const path = getWebhookSubscriptionRotateSecretApiPath(this.workspaceId, subscriptionId);
204
206
  return this.requestFn<WebhookSubscription>('POST', path);
205
207
  }
208
+
209
+ /**
210
+ * List the outbound payload versions a subscription can be pinned to via
211
+ * `create`/`update`'s `payloadVersion`. Each version selects the shape its
212
+ * deliveries are projected into; subscribers upgrade on their own timeline.
213
+ *
214
+ * @example
215
+ * ```ts
216
+ * const { data } = await centrali.webhookSubscriptions.getPayloadVersions();
217
+ * console.log('Latest payload version:', data.latest);
218
+ * ```
219
+ */
220
+ public getPayloadVersions(): Promise<ApiResponse<WebhookPayloadVersions>> {
221
+ const path = getWebhookPayloadVersionsApiPath(this.workspaceId);
222
+ return this.requestFn<WebhookPayloadVersions>('GET', path);
223
+ }
206
224
  }
@@ -102,6 +102,8 @@ export interface FunctionRun {
102
102
  triggerType?: string | null;
103
103
  orchestrationRunId?: string | null;
104
104
  orchestrationStepId?: string | null;
105
+ /** Inbound durable buffer link (CEN-1297) — set for buffered webhook-trigger runs. */
106
+ inboundEventId?: string | null;
105
107
  originalRunId?: string | null;
106
108
  isRerun: boolean;
107
109
  rerunCount: number;
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Types for the Event Log embed surface (CEN-1301).
3
+ *
4
+ * Mirrors the request/response shapes defined by IAM at
5
+ * services/backend/iam/src/controllers/embedTokenController.ts.
6
+ * Keep field names in sync with that controller's Zod schemas.
7
+ */
8
+
9
+ /**
10
+ * Capabilities that can be encoded into an embed token.
11
+ *
12
+ * - `events:read` — list + retrieve event-log rows for the tenant.
13
+ * IAM unconditionally injects this on every minted token, so omitting
14
+ * `capabilities` is equivalent to `['events:read']`.
15
+ * - `events:replay` — allow the iframe to replay a failed delivery. The
16
+ * issuing service account must also hold `webhook-subscriptions:replay`.
17
+ */
18
+ export type EmbedCapability = 'events:read' | 'events:replay';
19
+
20
+ export interface IssueEmbedTokenInput {
21
+ /**
22
+ * Tenant id the embed is allowed to read. Burned into the token claim;
23
+ * the data-service auto-injects this as a filter on every query the
24
+ * iframe makes. Centrali never interprets the bytes — treat it as
25
+ * opaque (1-255 chars).
26
+ */
27
+ tenantId: string;
28
+
29
+ /**
30
+ * Defaults to `['events:read']`. Pass `['events:read', 'events:replay']`
31
+ * to allow the iframe's "Replay" action. The issuing service account
32
+ * must already hold the corresponding capability.
33
+ */
34
+ capabilities?: EmbedCapability[];
35
+
36
+ /**
37
+ * Optional cohort id. Useful if you want to revoke every token issued
38
+ * for one of your end-users on logout — mint each with the same
39
+ * `sessionId`, then call `revokeSession({ sessionId })` later. Server
40
+ * mints a random one if omitted (returned in the response).
41
+ */
42
+ sessionId?: string;
43
+
44
+ /**
45
+ * Token TTL in seconds. Defaults to 600 (10 min). Capped at 3600 (1h)
46
+ * server-side; out-of-range values 400.
47
+ */
48
+ ttlSeconds?: number;
49
+ }
50
+
51
+ export interface IssueEmbedTokenResult {
52
+ /** `ev_…` JWT for the iframe's URL fragment. */
53
+ token: string;
54
+ /** Echo of the input sessionId, or the server-minted one if omitted. */
55
+ sessionId: string;
56
+ /** ISO-8601 timestamp at which the token's `exp` claim fires. */
57
+ expiresAt: string;
58
+ }
59
+
60
+ export interface RevokeEmbedSessionInput {
61
+ sessionId: string;
62
+ }
63
+
64
+ export interface RevokeEmbedSessionResult {
65
+ sessionId: string;
66
+ revokedAt: string;
67
+ }
@@ -22,6 +22,20 @@ export interface WebhookSubscription {
22
22
  * undefined on subsequent reads so it is safe to pass subscriptions around.
23
23
  */
24
24
  secret?: string;
25
+ /**
26
+ * Outbound payload version this subscription receives — a date-string
27
+ * (`YYYY-MM`). Deliveries are projected into the shape this version
28
+ * describes. Frozen at creation; change it to upgrade to a newer shape.
29
+ */
30
+ payloadVersion: string;
31
+ /**
32
+ * Opaque builder-supplied tenant identifier. Carried onto outbound
33
+ * delivery rows by the platform so embeds and tenant-scoped views can
34
+ * filter to a single customer without leaking cross-tenant events.
35
+ * Centrali never parses or interprets this value — it's the builder's
36
+ * own customer/account/workspace id, whatever shape that takes.
37
+ */
38
+ tenantId?: string | null;
25
39
  workspaceSlug: string;
26
40
  createdAt?: string;
27
41
  updatedAt?: string;
@@ -46,6 +60,8 @@ export interface WebhookDelivery {
46
60
  responseBody?: string | null;
47
61
  /** Delivery ID the row was replayed from, or null for original deliveries. */
48
62
  replayedFrom?: string | null;
63
+ /** Outbound payload version this delivery was projected into and served with. */
64
+ payloadVersion: string;
49
65
  createdAt: string;
50
66
  updatedAt: string;
51
67
  }
@@ -64,6 +80,19 @@ export interface CreateWebhookSubscriptionInput {
64
80
  /** Optional — restrict to a subset of collections. Omit for all collections. */
65
81
  recordSlugs?: string[];
66
82
  active?: boolean;
83
+ /**
84
+ * Optional outbound payload version to pin the subscription to. Omit to
85
+ * freeze to the latest version at creation time. Must be a value returned
86
+ * by `getPayloadVersions()`.
87
+ */
88
+ payloadVersion?: string;
89
+ /**
90
+ * Optional opaque tenant identifier — typically the builder's own
91
+ * customer or account id. Surfaces on every delivery the subscription
92
+ * produces so tenant-scoped views (e.g. an embedded Event Log) can
93
+ * filter to one customer.
94
+ */
95
+ tenantId?: string | null;
67
96
  }
68
97
 
69
98
  export interface UpdateWebhookSubscriptionInput {
@@ -77,6 +106,27 @@ export interface UpdateWebhookSubscriptionInput {
77
106
  */
78
107
  recordSlugs?: string[];
79
108
  active?: boolean;
109
+ /**
110
+ * Upgrade (or downgrade) the outbound payload version. Must be a value
111
+ * returned by `getPayloadVersions()`. Omit to leave the version unchanged.
112
+ */
113
+ payloadVersion?: string;
114
+ /**
115
+ * Update the opaque tenant identifier. Pass `null` to clear it; omit to
116
+ * leave it unchanged. Past deliveries are not retroactively rewritten —
117
+ * the new value applies to deliveries created after the update.
118
+ */
119
+ tenantId?: string | null;
120
+ }
121
+
122
+ /**
123
+ * Outbound payload versions a subscription can be pinned to. Returned by
124
+ * `getPayloadVersions()`. `versions` is oldest-first; `latest` is what a
125
+ * subscription created without an explicit version is frozen to.
126
+ */
127
+ export interface WebhookPayloadVersions {
128
+ versions: string[];
129
+ latest: string;
80
130
  }
81
131
 
82
132
  export interface ListWebhookDeliveriesOptions {