@sprigr/apps-app-sdk 0.29.0 → 0.31.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
@@ -976,6 +976,97 @@ declare function logToPlatform(env: WfpBridgeEnv, input: SprigrLogEntry | Sprigr
976
976
  */
977
977
  declare function withSprigrLogFallback<E extends WfpBridgeEnv & object>(env: E, opts?: LogToPlatformOptions): E;
978
978
 
979
+ /**
980
+ * `env.SPRIGR.report`: an app files a deduped platform report about a problem
981
+ * it found (sprigr-team decision 0262, sprigr-team#12208). The platform route
982
+ * is `POST /internal/wfp/report`; it stamps the app, install, installing
983
+ * company and publisher, scrubs credentials from title and detail, dedupes one
984
+ * report per app + key per window, caps new filings (5 per install per day,
985
+ * 20 per app per hour), and files severity 'critical' as 'high'.
986
+ *
987
+ * This module carries:
988
+ * 1. The types of the host member, so a call site is typed.
989
+ * 2. The route's limits, so an app can shape its input before calling.
990
+ * 3. The inline-route fallback (`reportToPlatform`), for code that runs
991
+ * where the host member is absent (an inline Next route).
992
+ *
993
+ * Unlike `env.SPRIGR.log`, the host member does NOT validate client-side and
994
+ * NEVER throws or rejects: a refused call resolves `{ ok: false, error }`
995
+ * with the route's error code. `reportToPlatform` keeps that contract.
996
+ */
997
+
998
+ /** Requested severity. The platform files 'critical' as 'high'. */
999
+ type SprigrReportSeverity = 'low' | 'medium' | 'high' | 'critical';
1000
+ declare const SPRIGR_REPORT_SEVERITIES: readonly SprigrReportSeverity[];
1001
+ interface SprigrReportInput {
1002
+ /** Stable identifier for this problem, e.g. "skip_empty_with_rows". Dedupe key per app. */
1003
+ key: string;
1004
+ /** One line, at most 200 chars. */
1005
+ title: string;
1006
+ /** Optional detail, at most 8000 chars. */
1007
+ detail?: string;
1008
+ /** Default 'medium'. */
1009
+ severity?: SprigrReportSeverity;
1010
+ /** Dedupe window in seconds. Default 86400, clamped to 3600..604800. */
1011
+ ttlSeconds?: number;
1012
+ }
1013
+ /**
1014
+ * What the host member resolves. It never rejects.
1015
+ * - `{ ok: true, status }`: filed, deduped (already filed in this window), or
1016
+ * rate_limited (a cap was reached; nothing filed).
1017
+ * - `{ ok: false, status: 'failed' }`: the platform accepted the call but the
1018
+ * filing itself failed.
1019
+ * - `{ ok: false, error }`: refused (`invalid_key`, `title_too_long`, ...),
1020
+ * a transport failure, `bindings_not_configured`, or `home_read_only` on a
1021
+ * Home dispatch.
1022
+ */
1023
+ type SprigrReportResult = {
1024
+ ok: true;
1025
+ status: 'filed' | 'deduped' | 'rate_limited';
1026
+ } | {
1027
+ ok: false;
1028
+ status: 'failed';
1029
+ } | {
1030
+ ok: false;
1031
+ error: string;
1032
+ detail?: string;
1033
+ status?: number;
1034
+ };
1035
+ /** Signature of the injected `env.SPRIGR.report`. */
1036
+ type SprigrReportFn = (input: SprigrReportInput) => Promise<SprigrReportResult>;
1037
+ /** Mirrors the platform route (sprigr-team `workers/provisioning/src/wfp-report.ts`). */
1038
+ declare const SPRIGR_REPORT_LIMITS: Readonly<{
1039
+ keyPattern: RegExp;
1040
+ maxTitleChars: 200;
1041
+ maxDetailChars: 8000;
1042
+ defaultTtlSeconds: number;
1043
+ minTtlSeconds: 3600;
1044
+ maxTtlSeconds: number;
1045
+ capPerInstallPerDay: 5;
1046
+ capPerAppPerHour: 20;
1047
+ }>;
1048
+ declare const DEFAULT_REPORT_TIMEOUT_MS = 5000;
1049
+ interface ReportToPlatformOptions {
1050
+ /** Override the 5s ceiling on the HTTP fallback. */
1051
+ timeoutMs?: number;
1052
+ /** `ctx.waitUntil` from the route handler, so the fallback fetch outlives the response. */
1053
+ waitUntil?: (p: Promise<unknown>) => void;
1054
+ }
1055
+ /** Whether a report could reach the platform by either transport. */
1056
+ declare function canReport(env: WfpBridgeEnv): boolean;
1057
+ /**
1058
+ * File a platform report from any execution context. Prefers the injected
1059
+ * `env.SPRIGR.report`; falls back to the install-token bridge when it is
1060
+ * absent. Never throws and never rejects.
1061
+ *
1062
+ * const r = await reportToPlatform(env, {
1063
+ * key: 'skip_empty_with_rows',
1064
+ * title: 'Upstream returned rows on a page marked empty',
1065
+ * detail: `page ${page}, ${rows.length} rows`,
1066
+ * }, { waitUntil: ctx.waitUntil.bind(ctx) });
1067
+ */
1068
+ declare function reportToPlatform(env: WfpBridgeEnv, input: SprigrReportInput, opts?: ReportToPlatformOptions): Promise<SprigrReportResult>;
1069
+
979
1070
  /**
980
1071
  * `env.SPRIGR.data.partialUpdate` from BOTH execution contexts.
981
1072
  *
@@ -3150,6 +3241,30 @@ declare function hasHtmlMarkup(body: string): boolean;
3150
3241
  */
3151
3242
  declare function emailBodyHtml(body: string): string;
3152
3243
 
3244
+ /**
3245
+ * The sending person's Inbox signature on mail an app sends as them
3246
+ * (sprigr-team decision 0255): one rule for every mail app, so the
3247
+ * microsoft-365 and google-workspace apps cannot drift apart.
3248
+ *
3249
+ * The platform resolves the person from the dispatch's signed actor
3250
+ * assertion (`env.SPRIGR.me.signature`); this only decides whether to append.
3251
+ * It appends when the bridge offers `me.signature`, the answer is ok and
3252
+ * carries html, the signature belongs to `senderPlatformUserId` (the owner of
3253
+ * the mailbox the mail goes out from), and the body does not already contain
3254
+ * it. The CALLER decides the mailbox: never call this for a shared or
3255
+ * delegated mailbox, nor for mail the Inbox composer wrote (it already seeded
3256
+ * the signature). Any refusal, missing bridge or failure returns the body
3257
+ * unchanged; a signature is never a reason to fail a send.
3258
+ */
3259
+
3260
+ declare function withSenderSignature(sprigr: {
3261
+ me?: Pick<SprigrMeApi, 'signature'>;
3262
+ } | undefined, args: {
3263
+ html: string;
3264
+ channel: string;
3265
+ senderPlatformUserId: string | undefined;
3266
+ }): Promise<string>;
3267
+
3153
3268
  /**
3154
3269
  * @sprigr/apps-app-sdk
3155
3270
  *
@@ -3526,6 +3641,42 @@ interface SprigrAssertionsApi {
3526
3641
  */
3527
3642
  mint(audience: string): Promise<SprigrAssertionMintResult>;
3528
3643
  }
3644
+ /** The `error` values {@link SprigrMeApi.signature} can resolve with. */
3645
+ type SprigrMeSignatureError = 'no_person' | 'actor_unverified' | 'invalid' | 'unavailable';
3646
+ /**
3647
+ * The result of {@link SprigrMeApi.signature} (sprigr-team decision 0255).
3648
+ * `ok: true` names the person whose signature it is (`platform_user_id`, a
3649
+ * `usr_` id) and their sanitized HTML signature, or `html: null` when they set
3650
+ * none. `ok: false` is a refusal; the method never rejects.
3651
+ */
3652
+ type SprigrMeSignatureResult = {
3653
+ ok: true;
3654
+ platform_user_id: string;
3655
+ html: string | null;
3656
+ } | {
3657
+ ok: false;
3658
+ error: SprigrMeSignatureError;
3659
+ message: string;
3660
+ };
3661
+ /**
3662
+ * `env.SPRIGR.me`: reads about the PERSON this dispatch acts for. The platform
3663
+ * resolves the person from the signed actor assertion on the dispatch, which
3664
+ * the bridge forwards itself; nothing an app passes can name another person.
3665
+ */
3666
+ interface SprigrMeApi {
3667
+ /**
3668
+ * The acting person's Inbox email signature for `channel` (the mail channel
3669
+ * slug, e.g. `'outlook_mail'` or `'google_mail'`): their override for that
3670
+ * channel's family if they set one, else their default. Append it only when
3671
+ * `platform_user_id` owns the mailbox you are sending from (never from a
3672
+ * shared mailbox), and skip it when the body already contains it.
3673
+ * Resolves `no_person` when nobody is acting (a webhook, an agent with no
3674
+ * person behind it, a member who left). Never rejects.
3675
+ */
3676
+ signature(input: {
3677
+ channel: string;
3678
+ }): Promise<SprigrMeSignatureResult>;
3679
+ }
3529
3680
  /**
3530
3681
  * Durable app file storage exposed on `env.SPRIGR.files` by the platform
3531
3682
  * wrapper (the platform build-runner). Persists bytes into the install's
@@ -3774,4 +3925,4 @@ interface ExecutionContextLike {
3774
3925
  }
3775
3926
  type HandlerFn<TArgs, TResult> = (args: TArgs, env: Record<string, unknown>, ctx?: ExecutionContextLike) => Promise<TResult>;
3776
3927
 
3777
- export { ACTOR_RETIRED_HOOK_TOOL, ACTOR_RETIRE_REASONS, APPROVAL_GRANTED_KEY, APPROVAL_PREVIEW_MAX, APP_FILES_ROOT, APP_OWNER_SEGMENT, type Actor, type ActorRetireReason, type ActorRetired, type ActorRetiredHookBody, type ActorRetiredResult, type AppApprovalEnvelope, type AppFileListItem, type AppFileUrlArgs, type AppFileUrlResult, type AppFilesEnv, type AppToolEffectsDeclaration, type AppUndoEnvelope, type ApplyPoliciesOptions, type ApprovalCoverage, type ApprovalGateOptions, type ApprovalPreviewFact, type ApprovalPreviewSlot, type ApprovalPreviewSpec, type ApprovalSpec, type ArchiveOfferOptions, type ArchiveOfferRefusal, type CallerKeyResolution, type CaptureJournal, type CompanyTimezoneEnv, type ConfirmCondition, type ConfirmRule, type ConfirmationPolicy, type ConnectCompleteRequest, type ConnectCompleteResult, type D1Like, type D1PreparedStatementLike, DATA_DELETE_MAX_IDS, DATA_PARTIAL_UPDATE_PATH, DEFAULT_EMIT_TIMEOUT_MS, DEFAULT_FILE_READ_TIMEOUT_MS, DEFAULT_LOG_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, DEFAULT_MONEY_FIELDS, DEFAULT_WRITE_PREFIXES, type DataClient, type DataIdsOpts, type DataListIdsResult, type DataTransport, type DerivePolicyOptions, type DerivedPolicy, type DispatcherApprovalGate, type DispatcherApprovalOptions, type EmailPreviewInput, type EmitMarketplaceEventOptions, type EmitResult, type EmitTransport, type EncodeStateWithinEnvelopeOptions, type EncodedStateWithinEnvelope, type EventArgs, type ExecutionContextLike, FILE_REF_SOURCES_HELP, type FetchFileResult, type FetchWithRetryOptions, type FileRef, type FileRefContent, type FileRefEnv, FileRefError, type FileRefErrorCode, type FileRefStream, type FileRefVia, type GetAppFileResult, type HandlerFn, INBOX_SEND_CONTRACT_V1, type IdPrefixSpec, type IdSnapshot, type InboxAddress, type InboxAppendRequest, type InboxAppendResult, type InboxChannelDeclaration, type InboxFoldersRequest, type InboxFoldersResult, type InboxOwner, type InboxSendConnection, type InboxSendHandlerImpl, InboxSendRefusal, type InboxSendSupports, type InboxSendV1Args, type InboxSendV1Result, type InstallBridge, InvalidUndoEnvelopeError, type JournalRowLike, type LogToPlatformOptions, type ManifestDispatchBlock, type ManifestLike, type ManifestToolLike, type MarketplaceEventEmitOpts, type MarketplaceEventSourceIntegration, NotConnectedError, OAUTH_STATE_ENVELOPE_MAX_CHARS, type OAuthBouncerSignals, type OAuthState, type OfferUndoArgs, type PartialUpdateDataOptions, type PlatformHostEnv, type PolicyCheckInput, type PolicySource, type PublicBaseUrlEnv, type PurgeResult, type PutAppFileArgs, type PutAppFileResult, type PutAppFileStreamArgs, type ReadFileRefOptions, type RequireApprovalOptions, type ResolveFileRefOptions, type ResolveViewerOptions, type ResolvedFileRef, type RestoreResult, type RestoreSpec, SPRIGR_DATA_MAX_OBJECTS_PER_CALL, SPRIGR_FILE_HOSTS, SPRIGR_LOG_LEVELS, SPRIGR_LOG_LIMITS, type ScheduleArgs, type SmsPreviewInput, type SprigrAssertionMintResult, type SprigrAssertionsApi, type SprigrDataAggregationCell, type SprigrDataAggregationResult, type SprigrDataAggregationSpec, type SprigrDataApi, type SprigrDataImportOpts, type SprigrDataIndexOpts, type SprigrDataPartialUpdateBody, type SprigrDataPartialUpdateOpts, type SprigrDataPartialUpdateResult, type SprigrDataPatch, type SprigrDataSearchOpts, type SprigrDataSearchResult, SprigrDataValidationError, type SprigrDataWriteTimeoutOpts, type SprigrFilesApi, type SprigrFilesApiWithEdit, type SprigrFilesCreateInput, type SprigrFilesCreateResult, type SprigrFilesEditInput, type SprigrFilesEditResult, type SprigrFilesJobResult, type SprigrFilesListItem, type SprigrFilesListResult, type SprigrInboxApi, type SprigrLogEntry, type SprigrLogFn, type SprigrLogLevel, type SprigrLogResult, SprigrLogValidationError, type SyncedAttachment, type SyncedMessage, type ToolArgs, type ToolHandler, type ToolResult, type ToolWrapperOptions, UNIT_SEP, type UndoApplyOptions, type UndoApplyResult, type UndoCaptureSpec, type UndoFidelity, VIEWER_ANONYMOUS, VIEWER_CONTEXT_HEADER, VIEWER_PLATFORM_USER_ID_HEADER, VIEWER_ROLE_HEADER, VIEWER_USER_ID_HEADER, type VerbRule, type ViewerContext, type ViewerContextFailure, type ViewerContextVerification, type ViewerEnv, WORKSPACE_FILE_HOW_TO, type WebhookArgs, type WfpBridgeEnv, type WfpEmitReply, actorKey, actorRetiredHook, actorTool, agentFileKeyFromUrl, appFileUrl, appKeyFromCallerKey, applyConfirmationPolicies, approvalHash, approvalPreview, approvalRecipients, archiveOfferRefusal, attendedFindings, base64ToBytes, buildConfirmationPolicy, buildMarketplaceWebhookUrl, buildPartialUpdateBody, bytesToBase64, callerKeyRefusal, canEmit, canLog, canPartialUpdate, checkConfirmationPolicy, commonDestructiveVerbs, connectComplete, connectDisconnect, constantTimeEqual, createMarketplaceEmitter, createToolWrappers, decodeState, defineInboxSendHandler, deleteAppFile, deleteSnapshotIds, deriveConfirmationPolicy, describeMissingBridge, dispatcherApproval, emailBodyHtml, emailPreview, emitMarketplaceEvent, encodeState, encodeStateWithinEnvelope, fetchFileAsBase64, fetchFileBytes, fetchWithRetry, fieldsPreview, fullWarning, getAppFile, getCompanyTimezone, hasHtmlMarkup, hmacSha256Hex, installTokenPost, isNotConnectedError, isStagingHost, listAppFiles, logToPlatform, makeDataClient, manifestIsFresh, oauthStateEnvelopeOverhead, offerUndo, openFileRef, overlaySprigr, ownerFromActorKey, parseActor, parseActorRetiredArgs, partialUpdateData, publicBaseUrl, purgeIndexByPrefix, putAppFile, putAppFileStream, randomHex, readFileRef, readableStoredKey, recreatedWarning, refuseWithoutForce, requireApproval, resolveFileRef, resolveInstallBridge, resolveOAuthBouncerBase, resolveOAuthBouncerCallbackUrl, resolvePlatformWebhookBase, resolveViewerContext, resolveViewerUserId, runUndoApply, safeCapture, seq, serializeManifest, set, smsPreview, snapshotIndexIds, tool, undoEnvelope, validateLogEntries, validateLogEntry, verifyViewerToken, withSprigrEmitFallback, withSprigrInboxFallback, withSprigrLogFallback };
3928
+ export { ACTOR_RETIRED_HOOK_TOOL, ACTOR_RETIRE_REASONS, APPROVAL_GRANTED_KEY, APPROVAL_PREVIEW_MAX, APP_FILES_ROOT, APP_OWNER_SEGMENT, type Actor, type ActorRetireReason, type ActorRetired, type ActorRetiredHookBody, type ActorRetiredResult, type AppApprovalEnvelope, type AppFileListItem, type AppFileUrlArgs, type AppFileUrlResult, type AppFilesEnv, type AppToolEffectsDeclaration, type AppUndoEnvelope, type ApplyPoliciesOptions, type ApprovalCoverage, type ApprovalGateOptions, type ApprovalPreviewFact, type ApprovalPreviewSlot, type ApprovalPreviewSpec, type ApprovalSpec, type ArchiveOfferOptions, type ArchiveOfferRefusal, type CallerKeyResolution, type CaptureJournal, type CompanyTimezoneEnv, type ConfirmCondition, type ConfirmRule, type ConfirmationPolicy, type ConnectCompleteRequest, type ConnectCompleteResult, type D1Like, type D1PreparedStatementLike, DATA_DELETE_MAX_IDS, DATA_PARTIAL_UPDATE_PATH, DEFAULT_EMIT_TIMEOUT_MS, DEFAULT_FILE_READ_TIMEOUT_MS, DEFAULT_LOG_TIMEOUT_MS, DEFAULT_MAX_FILE_BYTES, DEFAULT_MONEY_FIELDS, DEFAULT_REPORT_TIMEOUT_MS, DEFAULT_WRITE_PREFIXES, type DataClient, type DataIdsOpts, type DataListIdsResult, type DataTransport, type DerivePolicyOptions, type DerivedPolicy, type DispatcherApprovalGate, type DispatcherApprovalOptions, type EmailPreviewInput, type EmitMarketplaceEventOptions, type EmitResult, type EmitTransport, type EncodeStateWithinEnvelopeOptions, type EncodedStateWithinEnvelope, type EventArgs, type ExecutionContextLike, FILE_REF_SOURCES_HELP, type FetchFileResult, type FetchWithRetryOptions, type FileRef, type FileRefContent, type FileRefEnv, FileRefError, type FileRefErrorCode, type FileRefStream, type FileRefVia, type GetAppFileResult, type HandlerFn, INBOX_SEND_CONTRACT_V1, type IdPrefixSpec, type IdSnapshot, type InboxAddress, type InboxAppendRequest, type InboxAppendResult, type InboxChannelDeclaration, type InboxFoldersRequest, type InboxFoldersResult, type InboxOwner, type InboxSendConnection, type InboxSendHandlerImpl, InboxSendRefusal, type InboxSendSupports, type InboxSendV1Args, type InboxSendV1Result, type InstallBridge, InvalidUndoEnvelopeError, type JournalRowLike, type LogToPlatformOptions, type ManifestDispatchBlock, type ManifestLike, type ManifestToolLike, type MarketplaceEventEmitOpts, type MarketplaceEventSourceIntegration, NotConnectedError, OAUTH_STATE_ENVELOPE_MAX_CHARS, type OAuthBouncerSignals, type OAuthState, type OfferUndoArgs, type PartialUpdateDataOptions, type PlatformHostEnv, type PolicyCheckInput, type PolicySource, type PublicBaseUrlEnv, type PurgeResult, type PutAppFileArgs, type PutAppFileResult, type PutAppFileStreamArgs, type ReadFileRefOptions, type ReportToPlatformOptions, type RequireApprovalOptions, type ResolveFileRefOptions, type ResolveViewerOptions, type ResolvedFileRef, type RestoreResult, type RestoreSpec, SPRIGR_DATA_MAX_OBJECTS_PER_CALL, SPRIGR_FILE_HOSTS, SPRIGR_LOG_LEVELS, SPRIGR_LOG_LIMITS, SPRIGR_REPORT_LIMITS, SPRIGR_REPORT_SEVERITIES, type ScheduleArgs, type SmsPreviewInput, type SprigrAssertionMintResult, type SprigrAssertionsApi, type SprigrDataAggregationCell, type SprigrDataAggregationResult, type SprigrDataAggregationSpec, type SprigrDataApi, type SprigrDataImportOpts, type SprigrDataIndexOpts, type SprigrDataPartialUpdateBody, type SprigrDataPartialUpdateOpts, type SprigrDataPartialUpdateResult, type SprigrDataPatch, type SprigrDataSearchOpts, type SprigrDataSearchResult, SprigrDataValidationError, type SprigrDataWriteTimeoutOpts, type SprigrFilesApi, type SprigrFilesApiWithEdit, type SprigrFilesCreateInput, type SprigrFilesCreateResult, type SprigrFilesEditInput, type SprigrFilesEditResult, type SprigrFilesJobResult, type SprigrFilesListItem, type SprigrFilesListResult, type SprigrInboxApi, type SprigrLogEntry, type SprigrLogFn, type SprigrLogLevel, type SprigrLogResult, SprigrLogValidationError, type SprigrMeApi, type SprigrMeSignatureError, type SprigrMeSignatureResult, type SprigrReportFn, type SprigrReportInput, type SprigrReportResult, type SprigrReportSeverity, type SyncedAttachment, type SyncedMessage, type ToolArgs, type ToolHandler, type ToolResult, type ToolWrapperOptions, UNIT_SEP, type UndoApplyOptions, type UndoApplyResult, type UndoCaptureSpec, type UndoFidelity, VIEWER_ANONYMOUS, VIEWER_CONTEXT_HEADER, VIEWER_PLATFORM_USER_ID_HEADER, VIEWER_ROLE_HEADER, VIEWER_USER_ID_HEADER, type VerbRule, type ViewerContext, type ViewerContextFailure, type ViewerContextVerification, type ViewerEnv, WORKSPACE_FILE_HOW_TO, type WebhookArgs, type WfpBridgeEnv, type WfpEmitReply, actorKey, actorRetiredHook, actorTool, agentFileKeyFromUrl, appFileUrl, appKeyFromCallerKey, applyConfirmationPolicies, approvalHash, approvalPreview, approvalRecipients, archiveOfferRefusal, attendedFindings, base64ToBytes, buildConfirmationPolicy, buildMarketplaceWebhookUrl, buildPartialUpdateBody, bytesToBase64, callerKeyRefusal, canEmit, canLog, canPartialUpdate, canReport, checkConfirmationPolicy, commonDestructiveVerbs, connectComplete, connectDisconnect, constantTimeEqual, createMarketplaceEmitter, createToolWrappers, decodeState, defineInboxSendHandler, deleteAppFile, deleteSnapshotIds, deriveConfirmationPolicy, describeMissingBridge, dispatcherApproval, emailBodyHtml, emailPreview, emitMarketplaceEvent, encodeState, encodeStateWithinEnvelope, fetchFileAsBase64, fetchFileBytes, fetchWithRetry, fieldsPreview, fullWarning, getAppFile, getCompanyTimezone, hasHtmlMarkup, hmacSha256Hex, installTokenPost, isNotConnectedError, isStagingHost, listAppFiles, logToPlatform, makeDataClient, manifestIsFresh, oauthStateEnvelopeOverhead, offerUndo, openFileRef, overlaySprigr, ownerFromActorKey, parseActor, parseActorRetiredArgs, partialUpdateData, publicBaseUrl, purgeIndexByPrefix, putAppFile, putAppFileStream, randomHex, readFileRef, readableStoredKey, recreatedWarning, refuseWithoutForce, reportToPlatform, requireApproval, resolveFileRef, resolveInstallBridge, resolveOAuthBouncerBase, resolveOAuthBouncerCallbackUrl, resolvePlatformWebhookBase, resolveViewerContext, resolveViewerUserId, runUndoApply, safeCapture, seq, serializeManifest, set, smsPreview, snapshotIndexIds, tool, undoEnvelope, validateLogEntries, validateLogEntry, verifyViewerToken, withSenderSignature, withSprigrEmitFallback, withSprigrInboxFallback, withSprigrLogFallback };
package/dist/index.js CHANGED
@@ -960,6 +960,73 @@ function withSprigrLogFallback(env, opts) {
960
960
  return overlaySprigr(env, { ...existing, log });
961
961
  }
962
962
 
963
+ // src/platform-report.ts
964
+ var SPRIGR_REPORT_SEVERITIES = ["low", "medium", "high", "critical"];
965
+ var SPRIGR_REPORT_LIMITS = Object.freeze({
966
+ keyPattern: /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/,
967
+ maxTitleChars: 200,
968
+ maxDetailChars: 8e3,
969
+ defaultTtlSeconds: 24 * 3600,
970
+ minTtlSeconds: 3600,
971
+ maxTtlSeconds: 7 * 24 * 3600,
972
+ capPerInstallPerDay: 5,
973
+ capPerAppPerHour: 20
974
+ });
975
+ var DEFAULT_REPORT_TIMEOUT_MS = 5e3;
976
+ function bindingReport(env) {
977
+ const sprigr = env.SPRIGR;
978
+ return typeof sprigr?.report === "function" ? sprigr.report.bind(sprigr) : null;
979
+ }
980
+ function canReport(env) {
981
+ return bindingReport(env) !== null || resolveInstallBridge(env) !== null;
982
+ }
983
+ function failed(err) {
984
+ return { ok: false, error: "report_failed", detail: err instanceof Error ? err.message : String(err) };
985
+ }
986
+ async function postReport(env, input, timeoutMs) {
987
+ const bridge = resolveInstallBridge(env);
988
+ if (!bridge) {
989
+ return { ok: false, error: "bindings_not_configured", detail: describeMissingBridge(env) };
990
+ }
991
+ try {
992
+ const reply = await installTokenPost(bridge, "/internal/wfp/report", input ?? {}, { label: "report", timeoutMs });
993
+ if (reply.ok === true && (reply.status === "filed" || reply.status === "deduped" || reply.status === "rate_limited")) {
994
+ return { ok: true, status: reply.status };
995
+ }
996
+ if (reply.ok === false && reply.status === "failed") return { ok: false, status: "failed" };
997
+ return {
998
+ ok: false,
999
+ error: typeof reply.error === "string" ? reply.error : "report_failed",
1000
+ ...typeof reply.detail === "string" ? { detail: reply.detail } : {}
1001
+ };
1002
+ } catch (err) {
1003
+ const e = err;
1004
+ const message2 = e instanceof Error ? e.message : String(err);
1005
+ console.warn(`[sprigr-report] report fallback failed: ${message2}`);
1006
+ return {
1007
+ ok: false,
1008
+ error: e.error ?? (e.status !== void 0 ? "report_failed" : "report_transport_failed"),
1009
+ ...e.status !== void 0 ? { status: e.status } : {},
1010
+ detail: e.detail ?? message2
1011
+ };
1012
+ }
1013
+ }
1014
+ function reportToPlatform(env, input, opts) {
1015
+ const injected = bindingReport(env);
1016
+ let result;
1017
+ if (injected) {
1018
+ try {
1019
+ result = Promise.resolve(injected(input)).catch(failed);
1020
+ } catch (err) {
1021
+ result = Promise.resolve(failed(err));
1022
+ }
1023
+ } else {
1024
+ result = postReport(env, input, opts?.timeoutMs ?? DEFAULT_REPORT_TIMEOUT_MS);
1025
+ }
1026
+ if (opts?.waitUntil) opts.waitUntil(result);
1027
+ return result;
1028
+ }
1029
+
963
1030
  // src/platform-data.ts
964
1031
  var DATA_PARTIAL_UPDATE_PATH = "/internal/wfp/data/partial-update";
965
1032
  var SPRIGR_DATA_MAX_OBJECTS_PER_CALL = 1e3;
@@ -2318,6 +2385,22 @@ function emailBodyHtml(body) {
2318
2385
  if (normalized.length === 0) return body;
2319
2386
  return normalized.split(/\n[ \t]*\n+/).map((para) => `<p>${escapeHtml(para.replace(/^\n+|\n+$/g, "")).replace(/\n/g, "<br>")}</p>`).join("");
2320
2387
  }
2388
+
2389
+ // src/sender-signature.ts
2390
+ async function withSenderSignature(sprigr, args) {
2391
+ const me = sprigr?.me;
2392
+ if (!args.senderPlatformUserId || typeof me?.signature !== "function") return args.html;
2393
+ try {
2394
+ const sig = await me.signature({ channel: args.channel });
2395
+ if (!sig.ok || !sig.html) return args.html;
2396
+ if (sig.platform_user_id !== args.senderPlatformUserId) return args.html;
2397
+ if (args.html.includes(sig.html)) return args.html;
2398
+ return `${args.html}<br><br>-- <br>${sig.html}`;
2399
+ } catch (err) {
2400
+ console.warn("[app-sdk] env.SPRIGR.me.signature failed; sending without a signature:", err instanceof Error ? err.message : err);
2401
+ return args.html;
2402
+ }
2403
+ }
2321
2404
  export {
2322
2405
  ACTOR_RETIRED_HOOK_TOOL,
2323
2406
  ACTOR_RETIRE_REASONS,
@@ -2332,6 +2415,7 @@ export {
2332
2415
  DEFAULT_LOG_TIMEOUT_MS,
2333
2416
  DEFAULT_MAX_FILE_BYTES,
2334
2417
  DEFAULT_MONEY_FIELDS,
2418
+ DEFAULT_REPORT_TIMEOUT_MS,
2335
2419
  DEFAULT_WRITE_PREFIXES,
2336
2420
  FILE_REF_SOURCES_HELP,
2337
2421
  FileRefError,
@@ -2344,6 +2428,8 @@ export {
2344
2428
  SPRIGR_FILE_HOSTS,
2345
2429
  SPRIGR_LOG_LEVELS,
2346
2430
  SPRIGR_LOG_LIMITS,
2431
+ SPRIGR_REPORT_LIMITS,
2432
+ SPRIGR_REPORT_SEVERITIES,
2347
2433
  SprigrDataValidationError,
2348
2434
  SprigrLogValidationError,
2349
2435
  UNIT_SEP,
@@ -2374,6 +2460,7 @@ export {
2374
2460
  canEmit,
2375
2461
  canLog,
2376
2462
  canPartialUpdate,
2463
+ canReport,
2377
2464
  checkConfirmationPolicy,
2378
2465
  commonDestructiveVerbs,
2379
2466
  connectComplete,
@@ -2426,6 +2513,7 @@ export {
2426
2513
  readableStoredKey,
2427
2514
  recreatedWarning,
2428
2515
  refuseWithoutForce,
2516
+ reportToPlatform,
2429
2517
  requireApproval,
2430
2518
  resolveFileRef,
2431
2519
  resolveInstallBridge,
@@ -2446,6 +2534,7 @@ export {
2446
2534
  validateLogEntries,
2447
2535
  validateLogEntry,
2448
2536
  verifyViewerToken,
2537
+ withSenderSignature,
2449
2538
  withSprigrEmitFallback,
2450
2539
  withSprigrInboxFallback,
2451
2540
  withSprigrLogFallback
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sprigr/apps-app-sdk",
3
- "version": "0.29.0",
3
+ "version": "0.31.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",