@giveitsmaller/contracts 0.2.0 → 0.3.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/asyncapi/events.yaml +3617 -0
- package/availability/availability.json +2403 -0
- package/dist/asyncapi/AnonymousSchema_13.d.ts +6 -0
- package/dist/asyncapi/AnonymousSchema_13.js +7 -0
- package/dist/asyncapi/AnonymousSchema_152.d.ts +5 -0
- package/dist/asyncapi/AnonymousSchema_152.js +6 -0
- package/dist/asyncapi/Failure.d.ts +25 -0
- package/dist/asyncapi/Failure.js +1 -0
- package/dist/asyncapi/JobInputRole.d.ts +6 -0
- package/dist/asyncapi/JobInputRole.js +7 -0
- package/dist/asyncapi/MergeOutputType.d.ts +1 -3
- package/dist/asyncapi/MergeOutputType.js +0 -2
- package/dist/asyncapi/MultiOutputCompletion.d.ts +25 -0
- package/dist/asyncapi/MultiOutputCompletion.js +1 -0
- package/dist/asyncapi/NotificationsOperationsQueue.d.ts +4 -2
- package/dist/asyncapi/OperationMetrics.d.ts +3 -0
- package/dist/asyncapi/OperationProgress.d.ts +2 -0
- package/dist/asyncapi/OperationResult.d.ts +4 -19
- package/dist/asyncapi/OperationType.d.ts +6 -6
- package/dist/asyncapi/OperationType.js +5 -5
- package/dist/asyncapi/PageIndexed.d.ts +8 -0
- package/dist/asyncapi/PageIndexed.js +1 -0
- package/dist/asyncapi/PositionIndexed.d.ts +8 -0
- package/dist/asyncapi/PositionIndexed.js +1 -0
- package/dist/asyncapi/ProgressStatus.d.ts +3 -0
- package/dist/asyncapi/ProgressStatus.js +3 -0
- package/dist/asyncapi/ReEncodeDecision.d.ts +5 -0
- package/dist/asyncapi/ReEncodeDecision.js +6 -0
- package/dist/asyncapi/SingleOutputCompletion.d.ts +25 -0
- package/dist/asyncapi/SingleOutputCompletion.js +1 -0
- package/dist/asyncapi/SourceEntry.d.ts +2 -1
- package/dist/asyncapi/Unindexed.d.ts +8 -0
- package/dist/asyncapi/Unindexed.js +1 -0
- package/dist/asyncapi/UploadProbeCompletion.d.ts +16 -0
- package/dist/asyncapi/UploadProbeCompletion.js +1 -0
- package/dist/asyncapi/UploadProbeMediaMetadata.d.ts +18 -0
- package/dist/asyncapi/UploadProbeMediaMetadata.js +1 -0
- package/dist/asyncapi/UploadProbeProcessingClass.d.ts +6 -0
- package/dist/asyncapi/UploadProbeProcessingClass.js +7 -0
- package/dist/asyncapi/UploadProbeRequest.d.ts +10 -0
- package/dist/asyncapi/UploadProbeRequest.js +1 -0
- package/dist/asyncapi/UploadProbeStatus.d.ts +7 -0
- package/dist/asyncapi/UploadProbeStatus.js +8 -0
- package/dist/asyncapi/index.d.ts +13 -0
- package/dist/asyncapi/index.js +4 -0
- package/dist/openapi/models/AudioWatermarkDecodeRequest.d.ts +64 -0
- package/dist/openapi/models/AudioWatermarkDecodeRequest.js +53 -0
- package/dist/openapi/models/AudioWatermarkDecodeResponse.d.ts +80 -0
- package/dist/openapi/models/AudioWatermarkDecodeResponse.js +64 -0
- package/dist/openapi/models/AuthErrorResponse.d.ts +116 -0
- package/dist/openapi/models/AuthErrorResponse.js +66 -0
- package/dist/openapi/models/AuthErrorType.d.ts +73 -0
- package/dist/openapi/models/AuthErrorType.js +91 -0
- package/dist/openapi/models/AvailabilityValue.d.ts +43 -0
- package/dist/openapi/models/AvailabilityValue.js +61 -0
- package/dist/openapi/models/BalanceExhaustedResponse.d.ts +157 -0
- package/dist/openapi/models/BalanceExhaustedResponse.js +86 -0
- package/dist/openapi/models/BalanceExhaustedResponseAllOfLinks.d.ts +38 -0
- package/dist/openapi/models/BalanceExhaustedResponseAllOfLinks.js +43 -0
- package/dist/openapi/models/CallbackEventType.d.ts +2 -2
- package/dist/openapi/models/CallbackEventType.js +2 -2
- package/dist/openapi/models/ConnectionSource.d.ts +64 -0
- package/dist/openapi/models/ConnectionSource.js +57 -0
- package/dist/openapi/models/ContactRequest.d.ts +2 -2
- package/dist/openapi/models/ContactRequest.js +2 -2
- package/dist/openapi/models/ContactSubject.d.ts +2 -2
- package/dist/openapi/models/ContactSubject.js +2 -2
- package/dist/openapi/models/ContactValidationErrorResponse.d.ts +2 -2
- package/dist/openapi/models/ContactValidationErrorResponse.js +2 -2
- package/dist/openapi/models/CreateExternalImport403Response.d.ts +24 -0
- package/dist/openapi/models/CreateExternalImport403Response.js +58 -0
- package/dist/openapi/models/CreateWorkflow422Response.d.ts +23 -0
- package/dist/openapi/models/CreateWorkflow422Response.js +51 -0
- package/dist/openapi/models/CreditTransaction.d.ts +186 -0
- package/dist/openapi/models/CreditTransaction.js +100 -0
- package/dist/openapi/models/CreditTransactionSourceBucket.d.ts +46 -0
- package/dist/openapi/models/CreditTransactionSourceBucket.js +64 -0
- package/dist/openapi/models/CreditsBalanceResponse.d.ts +84 -0
- package/dist/openapi/models/CreditsBalanceResponse.js +68 -0
- package/dist/openapi/models/CreditsBalanceSuccessEnvelope.d.ts +46 -0
- package/dist/openapi/models/CreditsBalanceSuccessEnvelope.js +54 -0
- package/dist/openapi/models/CreditsUsageResponse.d.ts +51 -0
- package/dist/openapi/models/CreditsUsageResponse.js +56 -0
- package/dist/openapi/models/CreditsUsageSuccessEnvelope.d.ts +46 -0
- package/dist/openapi/models/CreditsUsageSuccessEnvelope.js +54 -0
- package/dist/openapi/models/Delivery.d.ts +98 -0
- package/dist/openapi/models/Delivery.js +65 -0
- package/dist/openapi/models/DeliveryOutputRef.d.ts +44 -0
- package/dist/openapi/models/DeliveryOutputRef.js +45 -0
- package/dist/openapi/models/DeliveryPlan.d.ts +77 -0
- package/dist/openapi/models/DeliveryPlan.js +72 -0
- package/dist/openapi/models/DeliveryPlanOutput.d.ts +53 -0
- package/dist/openapi/models/DeliveryPlanOutput.js +52 -0
- package/dist/openapi/models/DeliveryPlanReason.d.ts +35 -0
- package/dist/openapi/models/DeliveryPlanReason.js +53 -0
- package/dist/openapi/models/DeliverySelection.d.ts +62 -0
- package/dist/openapi/models/DeliverySelection.js +54 -0
- package/dist/openapi/models/ErrorEnvelope.d.ts +83 -5
- package/dist/openapi/models/ErrorEnvelope.js +10 -2
- package/dist/openapi/models/EstimateQuality.d.ts +34 -0
- package/dist/openapi/models/EstimateQuality.js +52 -0
- package/dist/openapi/models/EstimateRange.d.ts +48 -0
- package/dist/openapi/models/EstimateRange.js +51 -0
- package/dist/openapi/models/ExternalDestination.d.ts +41 -0
- package/dist/openapi/models/ExternalDestination.js +47 -0
- package/dist/openapi/models/ExternalImportCreatedResponse.d.ts +49 -0
- package/dist/openapi/models/ExternalImportCreatedResponse.js +51 -0
- package/dist/openapi/models/ExternalImportCreatedSuccessEnvelope.d.ts +46 -0
- package/dist/openapi/models/ExternalImportCreatedSuccessEnvelope.js +54 -0
- package/dist/openapi/models/ExternalImportRequest.d.ts +92 -0
- package/dist/openapi/models/ExternalImportRequest.js +61 -0
- package/dist/openapi/models/ExternalImportToken.d.ts +51 -0
- package/dist/openapi/models/ExternalImportToken.js +53 -0
- package/dist/openapi/models/ExternalSource.d.ts +31 -0
- package/dist/openapi/models/ExternalSource.js +47 -0
- package/dist/openapi/models/FeatureNotAvailableResponse.d.ts +140 -0
- package/dist/openapi/models/FeatureNotAvailableResponse.js +76 -0
- package/dist/openapi/models/FeatureTierRestrictedResponse.d.ts +135 -0
- package/dist/openapi/models/FeatureTierRestrictedResponse.js +76 -0
- package/dist/openapi/models/FeatureViolation.d.ts +108 -0
- package/dist/openapi/models/FeatureViolation.js +63 -0
- package/dist/openapi/models/JobDefinition.d.ts +125 -14
- package/dist/openapi/models/JobDefinition.js +25 -4
- package/dist/openapi/models/JobDownload.d.ts +2 -2
- package/dist/openapi/models/JobDownload.js +2 -2
- package/dist/openapi/models/JobInputV2.d.ts +89 -0
- package/dist/openapi/models/JobInputV2.js +56 -0
- package/dist/openapi/models/JobOutputSource.d.ts +57 -0
- package/dist/openapi/models/JobOutputSource.js +55 -0
- package/dist/openapi/models/JobResponse.d.ts +2 -2
- package/dist/openapi/models/JobResponse.js +2 -2
- package/dist/openapi/models/JobStatus.d.ts +17 -8
- package/dist/openapi/models/JobStatus.js +17 -8
- package/dist/openapi/models/JobType.d.ts +2 -2
- package/dist/openapi/models/JobType.js +2 -2
- package/dist/openapi/models/LivenessResponse.d.ts +2 -2
- package/dist/openapi/models/LivenessResponse.js +2 -2
- package/dist/openapi/models/LoginUser200Response.d.ts +46 -0
- package/dist/openapi/models/LoginUser200Response.js +54 -0
- package/dist/openapi/models/LoginUser200ResponseData.d.ts +33 -0
- package/dist/openapi/models/LoginUser200ResponseData.js +44 -0
- package/dist/openapi/models/LoginUser200ResponseDataUser.d.ts +50 -0
- package/dist/openapi/models/LoginUser200ResponseDataUser.js +51 -0
- package/dist/openapi/models/LoginUserRequest.d.ts +38 -0
- package/dist/openapi/models/LoginUserRequest.js +47 -0
- package/dist/openapi/models/LogoutUser200Response.d.ts +50 -0
- package/dist/openapi/models/LogoutUser200Response.js +53 -0
- package/dist/openapi/models/MetadataResponse.d.ts +13 -2
- package/dist/openapi/models/MetadataResponse.js +6 -2
- package/dist/openapi/models/MetadataResponseDimensions.d.ts +2 -2
- package/dist/openapi/models/MetadataResponseDimensions.js +2 -2
- package/dist/openapi/models/MetadataResponseExif.d.ts +2 -2
- package/dist/openapi/models/MetadataResponseExif.js +3 -3
- package/dist/openapi/models/MetadataResponseExifGps.d.ts +2 -2
- package/dist/openapi/models/MetadataResponseExifGps.js +2 -2
- package/dist/openapi/models/MetadataSuccessEnvelope.d.ts +3 -3
- package/dist/openapi/models/MetadataSuccessEnvelope.js +2 -2
- package/dist/openapi/models/MimeGroupSchema.d.ts +46 -2
- package/dist/openapi/models/MimeGroupSchema.js +11 -2
- package/dist/openapi/models/MultipartCompleteRequest.d.ts +4 -4
- package/dist/openapi/models/MultipartCompleteRequest.js +5 -5
- package/dist/openapi/models/MultipartCompleteRequestPartsInner.d.ts +2 -2
- package/dist/openapi/models/MultipartCompleteRequestPartsInner.js +2 -2
- package/dist/openapi/models/MultipartCompleteResponse.d.ts +53 -0
- package/dist/openapi/models/MultipartCompleteResponse.js +53 -0
- package/dist/openapi/models/MultipartCompleteSuccessEnvelope.d.ts +46 -0
- package/dist/openapi/models/MultipartCompleteSuccessEnvelope.js +54 -0
- package/dist/openapi/models/MultipartInitiateRequestMetadataHint.d.ts +56 -0
- package/dist/openapi/models/MultipartInitiateRequestMetadataHint.js +45 -0
- package/dist/openapi/models/MultipartInitiateResponse.d.ts +20 -4
- package/dist/openapi/models/MultipartInitiateResponse.js +10 -5
- package/dist/openapi/models/MultipartInitiateSuccessEnvelope.d.ts +3 -3
- package/dist/openapi/models/MultipartInitiateSuccessEnvelope.js +2 -2
- package/dist/openapi/models/OperationDefinition.d.ts +2 -2
- package/dist/openapi/models/OperationDefinition.js +2 -2
- package/dist/openapi/models/OperationDownload.d.ts +2 -2
- package/dist/openapi/models/OperationDownload.js +2 -2
- package/dist/openapi/models/OperationInputModel.d.ts +4 -4
- package/dist/openapi/models/OperationInputModel.js +4 -4
- package/dist/openapi/models/OperationResponse.d.ts +2 -2
- package/dist/openapi/models/OperationResponse.js +2 -2
- package/dist/openapi/models/OperationResult.d.ts +2 -2
- package/dist/openapi/models/OperationResult.js +2 -2
- package/dist/openapi/models/OperationResultMetrics.d.ts +2 -2
- package/dist/openapi/models/OperationResultMetrics.js +2 -2
- package/dist/openapi/models/OperationSchemaDefinition.d.ts +52 -5
- package/dist/openapi/models/OperationSchemaDefinition.js +10 -6
- package/dist/openapi/models/OperationStatus.d.ts +2 -2
- package/dist/openapi/models/OperationStatus.js +2 -2
- package/dist/openapi/models/OperationType.d.ts +17 -5
- package/dist/openapi/models/OperationType.js +18 -6
- package/dist/openapi/models/OperationsSchemaResponse.d.ts +70 -10
- package/dist/openapi/models/OperationsSchemaResponse.js +17 -2
- package/dist/openapi/models/OptionSchema.d.ts +42 -4
- package/dist/openapi/models/OptionSchema.js +12 -2
- package/dist/openapi/models/PerValueAvailabilityEntry.d.ts +80 -0
- package/dist/openapi/models/PerValueAvailabilityEntry.js +53 -0
- package/dist/openapi/models/PresignedUrlPart.d.ts +2 -2
- package/dist/openapi/models/PresignedUrlPart.js +3 -3
- package/dist/openapi/models/ProcessingClass.d.ts +35 -0
- package/dist/openapi/models/ProcessingClass.js +53 -0
- package/dist/openapi/models/ProcessingClassHint.d.ts +36 -0
- package/dist/openapi/models/ProcessingClassHint.js +54 -0
- package/dist/openapi/models/ProcessingClassReason.d.ts +46 -0
- package/dist/openapi/models/ProcessingClassReason.js +64 -0
- package/dist/openapi/models/ProcessingPlan.d.ts +70 -0
- package/dist/openapi/models/ProcessingPlan.js +49 -0
- package/dist/openapi/models/ProcessingPlanJob.d.ts +81 -0
- package/dist/openapi/models/ProcessingPlanJob.js +71 -0
- package/dist/openapi/models/ReadinessResponse.d.ts +2 -2
- package/dist/openapi/models/ReadinessResponse.js +2 -2
- package/dist/openapi/models/ResponseEnvelope.d.ts +2 -2
- package/dist/openapi/models/ResponseEnvelope.js +2 -2
- package/dist/openapi/models/RetryResponse.d.ts +5 -5
- package/dist/openapi/models/RetryResponse.js +2 -2
- package/dist/openapi/models/RetrySuccessEnvelope.d.ts +3 -3
- package/dist/openapi/models/RetrySuccessEnvelope.js +2 -2
- package/dist/openapi/models/SseEventType.d.ts +2 -2
- package/dist/openapi/models/SseEventType.js +2 -2
- package/dist/openapi/models/SseJobCompletedData.d.ts +3 -3
- package/dist/openapi/models/SseJobCompletedData.js +2 -2
- package/dist/openapi/models/SseJobFailedData.d.ts +3 -3
- package/dist/openapi/models/SseJobFailedData.js +2 -2
- package/dist/openapi/models/SseOperationCompletedData.d.ts +4 -4
- package/dist/openapi/models/SseOperationCompletedData.js +2 -2
- package/dist/openapi/models/SseOperationFailedData.d.ts +3 -3
- package/dist/openapi/models/SseOperationFailedData.js +2 -2
- package/dist/openapi/models/SseOperationProgressData.d.ts +61 -3
- package/dist/openapi/models/SseOperationProgressData.js +22 -2
- package/dist/openapi/models/SseWorkflowTerminalData.d.ts +26 -4
- package/dist/openapi/models/SseWorkflowTerminalData.js +4 -2
- package/dist/openapi/models/TierRestrictionKind.d.ts +33 -0
- package/dist/openapi/models/TierRestrictionKind.js +51 -0
- package/dist/openapi/models/TierRestrictionResponse.d.ts +154 -0
- package/dist/openapi/models/TierRestrictionResponse.js +83 -0
- package/dist/openapi/models/UploadConstraintsApplied.d.ts +70 -0
- package/dist/openapi/models/UploadConstraintsApplied.js +57 -0
- package/dist/openapi/models/UploadDurationExceedsTierResponse.d.ts +136 -0
- package/dist/openapi/models/UploadDurationExceedsTierResponse.js +82 -0
- package/dist/openapi/models/UploadFile403Response.d.ts +27 -0
- package/dist/openapi/models/UploadFile403Response.js +47 -0
- package/dist/openapi/models/UploadFile422Response.d.ts +27 -0
- package/dist/openapi/models/UploadFile422Response.js +47 -0
- package/dist/openapi/models/UploadProbeMediaMetadata.d.ts +172 -0
- package/dist/openapi/models/UploadProbeMediaMetadata.js +69 -0
- package/dist/openapi/models/UploadProbeProcessingClass.d.ts +33 -0
- package/dist/openapi/models/UploadProbeProcessingClass.js +51 -0
- package/dist/openapi/models/UploadProbeResponse.d.ts +58 -0
- package/dist/openapi/models/UploadProbeResponse.js +58 -0
- package/dist/openapi/models/UploadProbeStatus.d.ts +41 -0
- package/dist/openapi/models/UploadProbeStatus.js +59 -0
- package/dist/openapi/models/UploadResponse.d.ts +17 -3
- package/dist/openapi/models/UploadResponse.js +7 -2
- package/dist/openapi/models/UploadSizeExceedsTierResponse.d.ts +136 -0
- package/dist/openapi/models/UploadSizeExceedsTierResponse.js +82 -0
- package/dist/openapi/models/UploadSource.d.ts +48 -0
- package/dist/openapi/models/UploadSource.js +53 -0
- package/dist/openapi/models/UploadSuccessEnvelope.d.ts +3 -3
- package/dist/openapi/models/UploadSuccessEnvelope.js +2 -2
- package/dist/openapi/models/UploadThresholds.d.ts +119 -0
- package/dist/openapi/models/UploadThresholds.js +79 -0
- package/dist/openapi/models/UserTier.d.ts +41 -0
- package/dist/openapi/models/UserTier.js +59 -0
- package/dist/openapi/models/ValidationErrorEnvelope.d.ts +51 -4
- package/dist/openapi/models/ValidationErrorEnvelope.js +10 -2
- package/dist/openapi/models/ValidationErrorEnvelopeDetailsInner.d.ts +37 -4
- package/dist/openapi/models/ValidationErrorEnvelopeDetailsInner.js +6 -2
- package/dist/openapi/models/WarningType.d.ts +48 -0
- package/dist/openapi/models/WarningType.js +66 -0
- package/dist/openapi/models/WebhookOperationContext.d.ts +3 -3
- package/dist/openapi/models/WebhookOperationContext.js +2 -2
- package/dist/openapi/models/WebhookPayload.d.ts +2 -2
- package/dist/openapi/models/WebhookPayload.js +3 -3
- package/dist/openapi/models/WorkflowCancelBillingEffect.d.ts +36 -0
- package/dist/openapi/models/WorkflowCancelBillingEffect.js +54 -0
- package/dist/openapi/models/WorkflowCancelResponse.d.ts +66 -0
- package/dist/openapi/models/WorkflowCancelResponse.js +62 -0
- package/dist/openapi/models/WorkflowCancelSuccessEnvelope.d.ts +46 -0
- package/dist/openapi/models/WorkflowCancelSuccessEnvelope.js +54 -0
- package/dist/openapi/models/WorkflowCreateRequest.d.ts +39 -5
- package/dist/openapi/models/WorkflowCreateRequest.js +11 -5
- package/dist/openapi/models/WorkflowCreateResponse.d.ts +63 -2
- package/dist/openapi/models/WorkflowCreateResponse.js +21 -2
- package/dist/openapi/models/WorkflowCreateSuccessEnvelope.d.ts +3 -3
- package/dist/openapi/models/WorkflowCreateSuccessEnvelope.js +2 -2
- package/dist/openapi/models/WorkflowDownloadResponse.d.ts +2 -2
- package/dist/openapi/models/WorkflowDownloadResponse.js +2 -2
- package/dist/openapi/models/WorkflowDownloadSuccessEnvelope.d.ts +3 -3
- package/dist/openapi/models/WorkflowDownloadSuccessEnvelope.js +2 -2
- package/dist/openapi/models/WorkflowEdge.d.ts +2 -2
- package/dist/openapi/models/WorkflowEdge.js +2 -2
- package/dist/openapi/models/WorkflowExpiredResponse.d.ts +126 -0
- package/dist/openapi/models/WorkflowExpiredResponse.js +75 -0
- package/dist/openapi/models/WorkflowPauseRequiredAction.d.ts +30 -0
- package/dist/openapi/models/WorkflowPauseRequiredAction.js +48 -0
- package/dist/openapi/models/WorkflowPausedDetail.d.ts +99 -0
- package/dist/openapi/models/WorkflowPausedDetail.js +65 -0
- package/dist/openapi/models/WorkflowPausedDetailLinks.d.ts +47 -0
- package/dist/openapi/models/WorkflowPausedDetailLinks.js +45 -0
- package/dist/openapi/models/WorkflowProcessing.d.ts +36 -0
- package/dist/openapi/models/WorkflowProcessing.js +42 -0
- package/dist/openapi/models/WorkflowResumeResponse.d.ts +55 -0
- package/dist/openapi/models/WorkflowResumeResponse.js +57 -0
- package/dist/openapi/models/WorkflowResumeSuccessEnvelope.d.ts +46 -0
- package/dist/openapi/models/WorkflowResumeSuccessEnvelope.js +54 -0
- package/dist/openapi/models/WorkflowSource.d.ts +40 -0
- package/dist/openapi/models/WorkflowSource.js +57 -0
- package/dist/openapi/models/WorkflowStatus.d.ts +31 -8
- package/dist/openapi/models/WorkflowStatus.js +32 -9
- package/dist/openapi/models/WorkflowStatusResponse.d.ts +34 -2
- package/dist/openapi/models/WorkflowStatusResponse.js +13 -2
- package/dist/openapi/models/WorkflowStatusSuccessEnvelope.d.ts +3 -3
- package/dist/openapi/models/WorkflowStatusSuccessEnvelope.js +2 -2
- package/dist/openapi/models/WorkflowWarning.d.ts +119 -0
- package/dist/openapi/models/WorkflowWarning.js +63 -0
- package/dist/openapi/models/WorkflowWarningSeverity.d.ts +29 -0
- package/dist/openapi/models/WorkflowWarningSeverity.js +47 -0
- package/dist/openapi/models/index.d.ts +77 -3
- package/dist/openapi/models/index.js +77 -3
- package/dist/openapi/runtime.d.ts +2 -2
- package/dist/openapi/runtime.js +17 -2
- package/dist/operations/archive.metadata.d.ts +2 -0
- package/dist/operations/archive.metadata.js +13 -0
- package/dist/operations/audio_overlay.d.ts +48 -0
- package/dist/operations/audio_overlay.js +19 -0
- package/dist/operations/audio_overlay.metadata.d.ts +2 -0
- package/dist/operations/audio_overlay.metadata.js +167 -0
- package/dist/operations/audio_watermark.d.ts +42 -0
- package/dist/operations/audio_watermark.js +37 -0
- package/dist/operations/audio_watermark.metadata.d.ts +2 -0
- package/dist/operations/audio_watermark.metadata.js +94 -0
- package/dist/operations/compress.metadata.d.ts +2 -0
- package/dist/operations/compress.metadata.js +205 -0
- package/dist/operations/convert.metadata.d.ts +2 -0
- package/dist/operations/convert.metadata.js +85 -0
- package/dist/operations/custom_luma.d.ts +7 -0
- package/dist/operations/custom_luma.js +2 -0
- package/dist/operations/custom_luma.metadata.d.ts +2 -0
- package/dist/operations/custom_luma.metadata.js +49 -0
- package/dist/operations/image_watermark.d.ts +54 -0
- package/dist/operations/image_watermark.js +37 -0
- package/dist/operations/image_watermark.metadata.d.ts +2 -0
- package/dist/operations/image_watermark.metadata.js +97 -0
- package/dist/operations/index.d.ts +16 -1
- package/dist/operations/index.js +16 -1
- package/dist/operations/merge.d.ts +111 -31
- package/dist/operations/merge.js +106 -20
- package/dist/operations/merge.metadata.d.ts +2 -0
- package/dist/operations/merge.metadata.js +385 -0
- package/dist/operations/metadata-types.d.ts +47 -0
- package/dist/operations/metadata-types.js +2 -0
- package/dist/operations/text_watermark.d.ts +31 -0
- package/dist/operations/text_watermark.js +22 -0
- package/dist/operations/text_watermark.metadata.d.ts +2 -0
- package/dist/operations/text_watermark.metadata.js +46 -0
- package/dist/operations/thumbnail.metadata.d.ts +2 -0
- package/dist/operations/thumbnail.metadata.js +88 -0
- package/openapi/api.yaml +7154 -0
- package/operations/schemas/archive.yaml +22 -0
- package/operations/schemas/audio_overlay.yaml +397 -0
- package/operations/schemas/audio_watermark.yaml +184 -0
- package/operations/schemas/compress.yaml +297 -0
- package/operations/schemas/convert.yaml +119 -0
- package/operations/schemas/custom_luma.yaml +109 -0
- package/operations/schemas/image_watermark.yaml +280 -0
- package/operations/schemas/merge.yaml +440 -0
- package/operations/schemas/text_watermark.yaml +147 -0
- package/operations/schemas/thumbnail.yaml +135 -0
- package/package.json +20 -3
|
@@ -0,0 +1,3617 @@
|
|
|
1
|
+
asyncapi: 3.0.0
|
|
2
|
+
info:
|
|
3
|
+
title: GISL Compression Events
|
|
4
|
+
version: 3.2.0
|
|
5
|
+
description: |
|
|
6
|
+
Asynchronous event contracts for the GISL (Give It Smaller) compression service.
|
|
7
|
+
|
|
8
|
+
**Architecture Overview — Dual-Family SNS Topology**
|
|
9
|
+
|
|
10
|
+
The API publishes operation requests to **two** SNS topics, split by semantic
|
|
11
|
+
family. Each topic uses a single-attribute filter policy; there is no
|
|
12
|
+
compound-filter routing anywhere in the live topology:
|
|
13
|
+
|
|
14
|
+
- **`gisl-{env}-{region}-job-requests`** — compression routing only.
|
|
15
|
+
Filter attribute: `job_type`. Subscriptions: four per-media-type queues
|
|
16
|
+
(`jobs-image`, `jobs-video`, `jobs-audio`, `jobs-document`). Each
|
|
17
|
+
compression Lambda handles `compress` for exactly one media type.
|
|
18
|
+
- **`gisl-{env}-{region}-operations`** — non-compression operations
|
|
19
|
+
(thumbnail, image_watermark, text_watermark, merge, archive, convert,
|
|
20
|
+
custom_luma, audio_overlay, audio_watermark). Filter attribute:
|
|
21
|
+
`operation_type`. Subscriptions: one queue per operation type, plus four
|
|
22
|
+
thumbnail sub-type queues during the migration window. `custom_luma`,
|
|
23
|
+
`audio_overlay`, and `audio_watermark` are `availability: planned`
|
|
24
|
+
(per [I29](https://trello.com/c/EPUE5Vs1) +
|
|
25
|
+
[I19](https://trello.com/c/Xr3Z4GBF) +
|
|
26
|
+
[I20](https://trello.com/c/omiCq7Vn)) — their queues are declared
|
|
27
|
+
but receive no traffic until Lambda ships. `audio_watermark`
|
|
28
|
+
additionally requires `enterprise` tier.
|
|
29
|
+
|
|
30
|
+
**Publisher branching rule** (implemented in `compression_api`'s
|
|
31
|
+
`AwsSnsOperationPublisherAdapter` under Option A):
|
|
32
|
+
|
|
33
|
+
- For `operation_type == compress`: publish to the `job-requests` topic
|
|
34
|
+
with a single `job_type = {mediaGroup}` message attribute. Do **not**
|
|
35
|
+
set `operation_type` or `media_group` as attributes on this branch —
|
|
36
|
+
the media group is encoded as `job_type` and no other attribute is
|
|
37
|
+
used as a filter on this topic.
|
|
38
|
+
- For all other operation types: publish to the `operations` topic with
|
|
39
|
+
`operation_type = {type}` as the filter attribute. Additionally, set
|
|
40
|
+
`media_group = {mediaGroup}` as an informational message attribute
|
|
41
|
+
where a media group is meaningful (omit for archive). This second
|
|
42
|
+
attribute is **not** used as an SNS filter — it is preserved for
|
|
43
|
+
consumer observability and log correlation.
|
|
44
|
+
|
|
45
|
+
`media_group` is never a field in the message payload body. It exists
|
|
46
|
+
only as an SNS MessageAttribute on the `operations` topic branch.
|
|
47
|
+
|
|
48
|
+
**Thumbnail migration window.** The terraform topology has both the
|
|
49
|
+
legacy `ops-thumbnail` queue and four new sub-type queues
|
|
50
|
+
(`ops-thumbnail-{image,video,document,office}`) live simultaneously.
|
|
51
|
+
The API publisher currently emits the legacy `operation_type=thumbnail`
|
|
52
|
+
only; adoption of the four sub-type values (`thumbnail_image`,
|
|
53
|
+
`thumbnail_video`, `thumbnail_document`, `thumbnail_office`) is a
|
|
54
|
+
follow-up API PR. Both routing targets are documented in this contract
|
|
55
|
+
because both are valid during the migration.
|
|
56
|
+
|
|
57
|
+
**Notifications (Lambda -> API).** Lambda functions publish progress
|
|
58
|
+
and result notifications to the FIFO SNS topic
|
|
59
|
+
`gisl-{env}-{region}-notifications-operations.fifo`. The API consumes
|
|
60
|
+
from the corresponding FIFO SQS queue via a Raw Message Delivery
|
|
61
|
+
subscription. This notification path is unchanged from previous
|
|
62
|
+
releases.
|
|
63
|
+
|
|
64
|
+
**Lambda inventory** (post Option A):
|
|
65
|
+
|
|
66
|
+
- **Jobs family** (compression, 4 Lambdas), routed by `job_type`:
|
|
67
|
+
`compression-image`, `compression-video`, `compression-audio`,
|
|
68
|
+
`compression-document`. Each handles `compress` only for its media
|
|
69
|
+
type.
|
|
70
|
+
- **Operations family** (non-compression), routed by `operation_type`:
|
|
71
|
+
`operation-thumbnail` (legacy, retiring after migration),
|
|
72
|
+
`operation-thumbnail-image`, `operation-thumbnail-video`,
|
|
73
|
+
`operation-thumbnail-document`, `operation-thumbnail-office`,
|
|
74
|
+
`operation-image-watermark`, `operation-text-watermark`,
|
|
75
|
+
`operation-merge`, `operation-archive`,
|
|
76
|
+
`operation-convert`,
|
|
77
|
+
`operation-custom-luma` (planned per ticket I29 — not yet shipped),
|
|
78
|
+
`operation-audio-overlay` (planned per ticket I19 — not yet shipped),
|
|
79
|
+
`operation-audio-watermark` (planned per ticket I20 —
|
|
80
|
+
enterprise-tier; not yet shipped).
|
|
81
|
+
|
|
82
|
+
**Message Types**
|
|
83
|
+
|
|
84
|
+
- `JobRequest`: API -> compression Lambda (via `job-requests` topic).
|
|
85
|
+
- `OperationRequest`: API -> non-compression Lambda (via `operations`
|
|
86
|
+
topic).
|
|
87
|
+
- `OperationProgress`: Lambda -> API (progress updates, stored in Redis).
|
|
88
|
+
- `OperationResult`: Lambda -> API (terminal state, stored in DB).
|
|
89
|
+
|
|
90
|
+
`JobRequest` and `OperationRequest` share the same payload schema
|
|
91
|
+
(`OperationRequest`). They differ only in the SNS message attributes set
|
|
92
|
+
as headers, captured in two separate header schemas (`JobRequestAttributes`
|
|
93
|
+
and `OperationRequestAttributes`) so each topic's required attributes can
|
|
94
|
+
be enforced cleanly without conditional discriminators.
|
|
95
|
+
|
|
96
|
+
**Availability metadata.**
|
|
97
|
+
|
|
98
|
+
This spec uses the `x-availability` vendor extension as **decorative
|
|
99
|
+
documentation only**. Per [ADR-0001](../docs/decisions/0001-contract-first-availability.md)
|
|
100
|
+
§1.5, the runtime endpoint `GET /api/operations/schema` (ticket I3) is
|
|
101
|
+
the authoritative source; the sidecar `availability.json` (ticket I3b)
|
|
102
|
+
is the authoritative companion. SDKs MUST NOT depend on
|
|
103
|
+
`x-availability` reaching generated code — consumers read availability
|
|
104
|
+
from the runtime endpoint, not from the generated bindings.
|
|
105
|
+
|
|
106
|
+
The 5-value vocabulary (`stable | beta | experimental | planned |
|
|
107
|
+
deprecated`) is defined in the `AvailabilityValue` schema. See
|
|
108
|
+
`schemas/FORMAT.md` §Availability Taxonomy for operational rules
|
|
109
|
+
(parser obligation: absent = stable; per-enum-value granularity lands
|
|
110
|
+
via ticket I17 `per_value_availability` primitive).
|
|
111
|
+
|
|
112
|
+
servers:
|
|
113
|
+
local:
|
|
114
|
+
host: localhost:4566
|
|
115
|
+
protocol: sqs
|
|
116
|
+
description: LocalStack for local development
|
|
117
|
+
staging:
|
|
118
|
+
host: sqs.eu-west-1.amazonaws.com
|
|
119
|
+
protocol: sqs
|
|
120
|
+
description: AWS SQS - Staging environment
|
|
121
|
+
|
|
122
|
+
defaultContentType: application/json
|
|
123
|
+
|
|
124
|
+
channels:
|
|
125
|
+
# ============================================
|
|
126
|
+
# SNS REQUEST TOPICS (API -> Lambda)
|
|
127
|
+
# ============================================
|
|
128
|
+
|
|
129
|
+
jobRequestsTopic:
|
|
130
|
+
address: gisl-{env}-{region}-job-requests
|
|
131
|
+
description: |
|
|
132
|
+
SNS topic where the API publishes **compression** operation requests.
|
|
133
|
+
Filter attribute: `job_type` (single-attribute filter policy, not
|
|
134
|
+
compound). Subscriptions fan out to four per-media-type compression
|
|
135
|
+
queues, keyed by `job_type` value.
|
|
136
|
+
|
|
137
|
+
**Filter vocabulary:**
|
|
138
|
+
- `job_type = image` -> `jobs-image` queue
|
|
139
|
+
- `job_type = video` -> `jobs-video` queue
|
|
140
|
+
- `job_type = audio` -> `jobs-audio` queue
|
|
141
|
+
- `job_type = document` -> `jobs-document` queue
|
|
142
|
+
|
|
143
|
+
The API's Option A publisher sets only `job_type` as a message
|
|
144
|
+
attribute on this branch. `operation_type` and `media_group` are
|
|
145
|
+
**not** set on this branch — the media group is encoded as
|
|
146
|
+
`job_type` and no other attribute is used as a filter on this topic.
|
|
147
|
+
See the `publishJobRequest` operation below for the publisher
|
|
148
|
+
branching rule.
|
|
149
|
+
parameters:
|
|
150
|
+
env:
|
|
151
|
+
description: Environment (local, stg, prod)
|
|
152
|
+
region:
|
|
153
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
154
|
+
messages:
|
|
155
|
+
jobRequest:
|
|
156
|
+
$ref: '#/components/messages/JobRequestMessage'
|
|
157
|
+
|
|
158
|
+
operationsTopic:
|
|
159
|
+
address: gisl-{env}-{region}-operations
|
|
160
|
+
description: |
|
|
161
|
+
SNS topic where the API publishes **non-compression** operation
|
|
162
|
+
requests (thumbnail, image_watermark, text_watermark, merge, archive, convert, custom_luma, audio_overlay, audio_watermark). Filter
|
|
163
|
+
attribute: `operation_type` (single-attribute filter policy).
|
|
164
|
+
Subscriptions fan out to per-operation-type queues, keyed by
|
|
165
|
+
`operation_type` value.
|
|
166
|
+
|
|
167
|
+
**Filter vocabulary:**
|
|
168
|
+
- `operation_type = thumbnail` -> `ops-thumbnail` queue (legacy)
|
|
169
|
+
- `operation_type = thumbnail_image` -> `ops-thumbnail-image` queue
|
|
170
|
+
- `operation_type = thumbnail_video` -> `ops-thumbnail-video` queue
|
|
171
|
+
- `operation_type = thumbnail_document` -> `ops-thumbnail-document` queue
|
|
172
|
+
- `operation_type = thumbnail_office` -> `ops-thumbnail-office` queue
|
|
173
|
+
- `operation_type = image_watermark` -> `ops-image-watermark` queue
|
|
174
|
+
- `operation_type = text_watermark` -> `ops-text-watermark` queue
|
|
175
|
+
- `operation_type = merge` -> `ops-merge` queue
|
|
176
|
+
- `operation_type = archive` -> `ops-archive` queue
|
|
177
|
+
- `operation_type = convert` -> `ops-convert` queue
|
|
178
|
+
- `operation_type = custom_luma` -> `ops-custom-luma` queue (gated
|
|
179
|
+
by `availability: planned` until Lambda ships per
|
|
180
|
+
[I29](https://trello.com/c/EPUE5Vs1) — API rejects workflow-
|
|
181
|
+
create with `feature_not_available` (422) so no traffic reaches
|
|
182
|
+
the topic today)
|
|
183
|
+
- `operation_type = audio_overlay` -> `ops-audio-overlay` queue
|
|
184
|
+
(gated by `availability: planned` until Lambda ships per
|
|
185
|
+
[I19](https://trello.com/c/Xr3Z4GBF) — same `feature_not_
|
|
186
|
+
available` 422 gating)
|
|
187
|
+
- `operation_type = audio_watermark` -> `ops-audio-watermark`
|
|
188
|
+
queue (gated by `availability: planned` +
|
|
189
|
+
`required_tier: enterprise` per
|
|
190
|
+
[I20](https://trello.com/c/omiCq7Vn) — same 422 gating, plus
|
|
191
|
+
a 403 `feature_tier_restricted` for non-enterprise callers)
|
|
192
|
+
|
|
193
|
+
The API's Option A publisher sets `operation_type` as the filter
|
|
194
|
+
attribute and additionally sets `media_group` as an **informational**
|
|
195
|
+
message attribute where a media group is meaningful (omitted for
|
|
196
|
+
archive). `media_group` is **not** used by SNS as a routing filter
|
|
197
|
+
on this topic — it is preserved for consumer observability and log
|
|
198
|
+
correlation. See the `publishOperationRequest` operation below for
|
|
199
|
+
the publisher branching rule.
|
|
200
|
+
|
|
201
|
+
**Thumbnail migration window.** The legacy `ops-thumbnail` queue and
|
|
202
|
+
the four sub-type queues are all live simultaneously. The API
|
|
203
|
+
publisher currently emits `operation_type=thumbnail` (legacy);
|
|
204
|
+
adoption of the four sub-type values is a follow-up API PR. Both
|
|
205
|
+
paths are valid routing targets today.
|
|
206
|
+
parameters:
|
|
207
|
+
env:
|
|
208
|
+
description: Environment (local, stg, prod)
|
|
209
|
+
region:
|
|
210
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
211
|
+
messages:
|
|
212
|
+
operationRequest:
|
|
213
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
214
|
+
|
|
215
|
+
# ============================================
|
|
216
|
+
# JOBS FAMILY - COMPRESSION QUEUES (per media type)
|
|
217
|
+
# ============================================
|
|
218
|
+
|
|
219
|
+
jobsImage:
|
|
220
|
+
address: gisl-{env}-{region}-jobs-image
|
|
221
|
+
description: |
|
|
222
|
+
SQS queue for image compression jobs.
|
|
223
|
+
Subscribed to the `job-requests` SNS topic with filter
|
|
224
|
+
`job_type = image`. Handles `compress` only for image inputs.
|
|
225
|
+
parameters:
|
|
226
|
+
env:
|
|
227
|
+
description: Environment (local, stg, prod)
|
|
228
|
+
region:
|
|
229
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
230
|
+
messages:
|
|
231
|
+
jobRequest:
|
|
232
|
+
$ref: '#/components/messages/JobRequestMessage'
|
|
233
|
+
|
|
234
|
+
jobsVideo:
|
|
235
|
+
address: gisl-{env}-{region}-jobs-video
|
|
236
|
+
description: |
|
|
237
|
+
SQS queue for video compression jobs.
|
|
238
|
+
Subscribed to the `job-requests` SNS topic with filter
|
|
239
|
+
`job_type = video`. Handles `compress` only for video inputs.
|
|
240
|
+
parameters:
|
|
241
|
+
env:
|
|
242
|
+
description: Environment (local, stg, prod)
|
|
243
|
+
region:
|
|
244
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
245
|
+
messages:
|
|
246
|
+
jobRequest:
|
|
247
|
+
$ref: '#/components/messages/JobRequestMessage'
|
|
248
|
+
|
|
249
|
+
jobsAudio:
|
|
250
|
+
address: gisl-{env}-{region}-jobs-audio
|
|
251
|
+
description: |
|
|
252
|
+
SQS queue for audio compression jobs.
|
|
253
|
+
Subscribed to the `job-requests` SNS topic with filter
|
|
254
|
+
`job_type = audio`. Handles `compress` only for audio inputs.
|
|
255
|
+
parameters:
|
|
256
|
+
env:
|
|
257
|
+
description: Environment (local, stg, prod)
|
|
258
|
+
region:
|
|
259
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
260
|
+
messages:
|
|
261
|
+
jobRequest:
|
|
262
|
+
$ref: '#/components/messages/JobRequestMessage'
|
|
263
|
+
|
|
264
|
+
jobsDocument:
|
|
265
|
+
address: gisl-{env}-{region}-jobs-document
|
|
266
|
+
description: |
|
|
267
|
+
SQS queue for document compression jobs.
|
|
268
|
+
Subscribed to the `job-requests` SNS topic with filter
|
|
269
|
+
`job_type = document`. Handles `compress` only for document inputs.
|
|
270
|
+
parameters:
|
|
271
|
+
env:
|
|
272
|
+
description: Environment (local, stg, prod)
|
|
273
|
+
region:
|
|
274
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
275
|
+
messages:
|
|
276
|
+
jobRequest:
|
|
277
|
+
$ref: '#/components/messages/JobRequestMessage'
|
|
278
|
+
|
|
279
|
+
# ============================================
|
|
280
|
+
# JOBS FAMILY - DEAD LETTER QUEUES
|
|
281
|
+
# ============================================
|
|
282
|
+
|
|
283
|
+
jobsImageDlq:
|
|
284
|
+
address: gisl-{env}-{region}-jobs-image-dlq
|
|
285
|
+
description: DLQ for failed image compression jobs. Messages land here after 5 failed processing attempts.
|
|
286
|
+
parameters:
|
|
287
|
+
env:
|
|
288
|
+
description: Environment (local, stg, prod)
|
|
289
|
+
region:
|
|
290
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
291
|
+
|
|
292
|
+
jobsVideoDlq:
|
|
293
|
+
address: gisl-{env}-{region}-jobs-video-dlq
|
|
294
|
+
description: DLQ for failed video compression jobs. Messages land here after 5 failed processing attempts.
|
|
295
|
+
parameters:
|
|
296
|
+
env:
|
|
297
|
+
description: Environment (local, stg, prod)
|
|
298
|
+
region:
|
|
299
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
300
|
+
|
|
301
|
+
jobsAudioDlq:
|
|
302
|
+
address: gisl-{env}-{region}-jobs-audio-dlq
|
|
303
|
+
description: DLQ for failed audio compression jobs. Messages land here after 5 failed processing attempts.
|
|
304
|
+
parameters:
|
|
305
|
+
env:
|
|
306
|
+
description: Environment (local, stg, prod)
|
|
307
|
+
region:
|
|
308
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
309
|
+
|
|
310
|
+
jobsDocumentDlq:
|
|
311
|
+
address: gisl-{env}-{region}-jobs-document-dlq
|
|
312
|
+
description: DLQ for failed document compression jobs. Messages land here after 5 failed processing attempts.
|
|
313
|
+
parameters:
|
|
314
|
+
env:
|
|
315
|
+
description: Environment (local, stg, prod)
|
|
316
|
+
region:
|
|
317
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
318
|
+
|
|
319
|
+
# ============================================
|
|
320
|
+
# OPS FAMILY - NON-COMPRESSION OPERATION QUEUES
|
|
321
|
+
# ============================================
|
|
322
|
+
|
|
323
|
+
opsThumbnail:
|
|
324
|
+
address: gisl-{env}-{region}-ops-thumbnail
|
|
325
|
+
description: |
|
|
326
|
+
SQS queue for legacy thumbnail operations.
|
|
327
|
+
Subscribed to the `operations` SNS topic with filter
|
|
328
|
+
`operation_type = thumbnail`.
|
|
329
|
+
|
|
330
|
+
**Migration window**: This is the legacy routing target and is
|
|
331
|
+
currently the only one the API publisher emits for (via
|
|
332
|
+
`operation_type=thumbnail`). It handles thumbnail requests for all
|
|
333
|
+
media types. Retirement is planned after the API publisher adopts
|
|
334
|
+
the four sub-type values (`thumbnail_image`, `thumbnail_video`,
|
|
335
|
+
`thumbnail_document`, `thumbnail_office`) in a follow-up API PR.
|
|
336
|
+
parameters:
|
|
337
|
+
env:
|
|
338
|
+
description: Environment (local, stg, prod)
|
|
339
|
+
region:
|
|
340
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
341
|
+
messages:
|
|
342
|
+
operationRequest:
|
|
343
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
344
|
+
|
|
345
|
+
opsThumbnailImage:
|
|
346
|
+
address: gisl-{env}-{region}-ops-thumbnail-image
|
|
347
|
+
description: |
|
|
348
|
+
SQS queue for image thumbnail operations.
|
|
349
|
+
Subscribed to the `operations` SNS topic with filter
|
|
350
|
+
`operation_type = thumbnail_image`. Backed by the Rust image
|
|
351
|
+
thumbnail Lambda (`operation-thumbnail-image`).
|
|
352
|
+
|
|
353
|
+
Not yet receiving traffic — the API publisher currently emits
|
|
354
|
+
`operation_type=thumbnail` (legacy) and will flip to
|
|
355
|
+
`thumbnail_image` after a follow-up API PR adds input-MIME dispatch.
|
|
356
|
+
parameters:
|
|
357
|
+
env:
|
|
358
|
+
description: Environment (local, stg, prod)
|
|
359
|
+
region:
|
|
360
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
361
|
+
messages:
|
|
362
|
+
operationRequest:
|
|
363
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
364
|
+
|
|
365
|
+
opsThumbnailVideo:
|
|
366
|
+
address: gisl-{env}-{region}-ops-thumbnail-video
|
|
367
|
+
description: |
|
|
368
|
+
SQS queue for video thumbnail operations.
|
|
369
|
+
Subscribed to the `operations` SNS topic with filter
|
|
370
|
+
`operation_type = thumbnail_video`. Backed by the FFmpeg video
|
|
371
|
+
thumbnail Lambda (`operation-thumbnail-video`).
|
|
372
|
+
|
|
373
|
+
Not yet receiving traffic — the API publisher currently emits
|
|
374
|
+
`operation_type=thumbnail` (legacy) and will flip to
|
|
375
|
+
`thumbnail_video` after a follow-up API PR adds input-MIME dispatch.
|
|
376
|
+
parameters:
|
|
377
|
+
env:
|
|
378
|
+
description: Environment (local, stg, prod)
|
|
379
|
+
region:
|
|
380
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
381
|
+
messages:
|
|
382
|
+
operationRequest:
|
|
383
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
384
|
+
|
|
385
|
+
opsThumbnailDocument:
|
|
386
|
+
address: gisl-{env}-{region}-ops-thumbnail-document
|
|
387
|
+
description: |
|
|
388
|
+
SQS queue for PDF/EPUB document thumbnail operations.
|
|
389
|
+
Subscribed to the `operations` SNS topic with filter
|
|
390
|
+
`operation_type = thumbnail_document`. Backed by the Ghostscript
|
|
391
|
+
document thumbnail Lambda (`operation-thumbnail-document`).
|
|
392
|
+
|
|
393
|
+
Not yet receiving traffic — the API publisher currently emits
|
|
394
|
+
`operation_type=thumbnail` (legacy) and will flip to
|
|
395
|
+
`thumbnail_document` after a follow-up API PR adds input-MIME
|
|
396
|
+
dispatch.
|
|
397
|
+
parameters:
|
|
398
|
+
env:
|
|
399
|
+
description: Environment (local, stg, prod)
|
|
400
|
+
region:
|
|
401
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
402
|
+
messages:
|
|
403
|
+
operationRequest:
|
|
404
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
405
|
+
|
|
406
|
+
opsThumbnailOffice:
|
|
407
|
+
address: gisl-{env}-{region}-ops-thumbnail-office
|
|
408
|
+
description: |
|
|
409
|
+
SQS queue for office document thumbnail operations
|
|
410
|
+
(DOCX, XLSX, PPTX, ODT, ODS, ODP).
|
|
411
|
+
Subscribed to the `operations` SNS topic with filter
|
|
412
|
+
`operation_type = thumbnail_office`. Backed by the LibreOffice
|
|
413
|
+
thumbnail Lambda (`operation-thumbnail-office`).
|
|
414
|
+
|
|
415
|
+
Not yet receiving traffic — the API publisher currently emits
|
|
416
|
+
`operation_type=thumbnail` (legacy) and will flip to
|
|
417
|
+
`thumbnail_office` after a follow-up API PR adds input-MIME
|
|
418
|
+
dispatch.
|
|
419
|
+
parameters:
|
|
420
|
+
env:
|
|
421
|
+
description: Environment (local, stg, prod)
|
|
422
|
+
region:
|
|
423
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
424
|
+
messages:
|
|
425
|
+
operationRequest:
|
|
426
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
427
|
+
|
|
428
|
+
opsImageWatermark:
|
|
429
|
+
address: gisl-{env}-{region}-ops-image-watermark
|
|
430
|
+
description: |
|
|
431
|
+
SQS queue for image_watermark operations (multi-input).
|
|
432
|
+
Subscribed to the `operations` SNS topic with filter
|
|
433
|
+
`operation_type = image_watermark`. Handles image-overlay
|
|
434
|
+
watermarking with one `base` input + one `overlay` input
|
|
435
|
+
(per JobInputV2.role). Backed by the operation-image-watermark
|
|
436
|
+
Lambda (cross-repo X1 retirement target).
|
|
437
|
+
|
|
438
|
+
Stable today for image bases (jpeg/png/webp). Animated GIF and
|
|
439
|
+
video bases are advertised in `image_watermark.yaml` as `planned`
|
|
440
|
+
via parallel mime_groups (`image_gif`, `video` per I5 — Trello
|
|
441
|
+
AKZiOXnd); the publisher MAY route those `media_group` values to
|
|
442
|
+
this queue once Lambda support ships. Until then the API returns
|
|
443
|
+
`feature_not_available` (422) at workflow-create time and these
|
|
444
|
+
messages do not reach the queue. Per ADR-0004 + I4-CONS + I5.
|
|
445
|
+
parameters:
|
|
446
|
+
env:
|
|
447
|
+
description: Environment (local, stg, prod)
|
|
448
|
+
region:
|
|
449
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
450
|
+
messages:
|
|
451
|
+
operationRequest:
|
|
452
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
453
|
+
|
|
454
|
+
opsTextWatermark:
|
|
455
|
+
address: gisl-{env}-{region}-ops-text-watermark
|
|
456
|
+
description: |
|
|
457
|
+
SQS queue for text_watermark operations (single-input, image-only).
|
|
458
|
+
Subscribed to the `operations` SNS topic with filter
|
|
459
|
+
`operation_type = text_watermark`. Renders text overlays
|
|
460
|
+
(Liberation Sans) — supports `single` (one label at anchor) and
|
|
461
|
+
`tiled` (Cinavia-style angled fill) modes. Backed by the
|
|
462
|
+
operation-text-watermark Lambda. Per ADR-0004 + I4-CONS.
|
|
463
|
+
parameters:
|
|
464
|
+
env:
|
|
465
|
+
description: Environment (local, stg, prod)
|
|
466
|
+
region:
|
|
467
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
468
|
+
messages:
|
|
469
|
+
operationRequest:
|
|
470
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
471
|
+
|
|
472
|
+
opsMerge:
|
|
473
|
+
address: gisl-{env}-{region}-ops-merge
|
|
474
|
+
description: |
|
|
475
|
+
SQS queue for merge operations.
|
|
476
|
+
Subscribed to the `operations` SNS topic with filter
|
|
477
|
+
`operation_type = merge`. A single `operation-merge` Lambda handles
|
|
478
|
+
all merge output types (animated GIF, video slideshow/concat, audio
|
|
479
|
+
concat) — the `output_type` field on the request determines the
|
|
480
|
+
encoding path internally, not the routing. Image collage and PDF
|
|
481
|
+
concatenation are not supported by the V1 Lambda.
|
|
482
|
+
parameters:
|
|
483
|
+
env:
|
|
484
|
+
description: Environment (local, stg, prod)
|
|
485
|
+
region:
|
|
486
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
487
|
+
messages:
|
|
488
|
+
operationRequest:
|
|
489
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
490
|
+
|
|
491
|
+
opsArchive:
|
|
492
|
+
address: gisl-{env}-{region}-ops-archive
|
|
493
|
+
description: |
|
|
494
|
+
SQS queue for archive operations (ZIP/tar.gz bundling).
|
|
495
|
+
Subscribed to the `operations` SNS topic with filter
|
|
496
|
+
`operation_type = archive`. Media-agnostic: accepts mixed input
|
|
497
|
+
types. Backed by the archive Lambda (`operation-archive`).
|
|
498
|
+
parameters:
|
|
499
|
+
env:
|
|
500
|
+
description: Environment (local, stg, prod)
|
|
501
|
+
region:
|
|
502
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
503
|
+
messages:
|
|
504
|
+
operationRequest:
|
|
505
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
506
|
+
|
|
507
|
+
opsConvert:
|
|
508
|
+
address: gisl-{env}-{region}-ops-convert
|
|
509
|
+
description: |
|
|
510
|
+
SQS queue for convert operations (format conversion).
|
|
511
|
+
Subscribed to the `operations` SNS topic with filter
|
|
512
|
+
`operation_type = convert`. Handles format conversion across all
|
|
513
|
+
media types (image, video, audio, document). Backed by the convert
|
|
514
|
+
Lambda (`operation-convert`).
|
|
515
|
+
parameters:
|
|
516
|
+
env:
|
|
517
|
+
description: Environment (local, stg, prod)
|
|
518
|
+
region:
|
|
519
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
520
|
+
messages:
|
|
521
|
+
operationRequest:
|
|
522
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
523
|
+
|
|
524
|
+
opsCustomLuma:
|
|
525
|
+
address: gisl-{env}-{region}-ops-custom-luma
|
|
526
|
+
description: |
|
|
527
|
+
SQS queue for custom_luma operations (caller-uploaded luma matte
|
|
528
|
+
transition; pro-tier paid feature). Subscribed to the
|
|
529
|
+
`operations` SNS topic with filter `operation_type = custom_luma`.
|
|
530
|
+
Multi-input (Path B with `role: base` + `role: transition_mask`
|
|
531
|
+
per `JobInputV2.role`).
|
|
532
|
+
|
|
533
|
+
`custom_luma` is `availability: planned` + `required_tier: pro`
|
|
534
|
+
per the operation schema; the API rejects workflow-create with
|
|
535
|
+
`feature_not_available` (422) until the Lambda ships, so traffic
|
|
536
|
+
does not reach this queue today. Backed by the
|
|
537
|
+
`operation-custom-luma` Lambda (cross-repo follow-up; not yet
|
|
538
|
+
shipped).
|
|
539
|
+
Per ADR-0004 + I29 (Trello EPUE5Vs1).
|
|
540
|
+
parameters:
|
|
541
|
+
env:
|
|
542
|
+
description: Environment (local, stg, prod)
|
|
543
|
+
region:
|
|
544
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
545
|
+
messages:
|
|
546
|
+
operationRequest:
|
|
547
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
548
|
+
|
|
549
|
+
opsAudioOverlay:
|
|
550
|
+
address: gisl-{env}-{region}-ops-audio-overlay
|
|
551
|
+
description: |
|
|
552
|
+
SQS queue for audio_overlay operations (mix a secondary audio
|
|
553
|
+
asset over a primary audio or video base — DJ tags, podcast
|
|
554
|
+
intros/outros, station IDs, jingles). Subscribed to the
|
|
555
|
+
`operations` SNS topic with filter
|
|
556
|
+
`operation_type = audio_overlay`. Multi-input (Path B with
|
|
557
|
+
`role: base` + `role: overlay` per `JobInputV2.role`).
|
|
558
|
+
|
|
559
|
+
Both mime_groups (`audio`, `video`) are `availability: planned`;
|
|
560
|
+
the API rejects workflow-create with `feature_not_available`
|
|
561
|
+
(422) until the Lambda ships, so traffic does not reach this
|
|
562
|
+
queue today. Backed by the `operation-audio-overlay` Lambda
|
|
563
|
+
(cross-repo follow-up; not yet shipped).
|
|
564
|
+
|
|
565
|
+
**NOT** the same as `audio_watermark` — that operation is
|
|
566
|
+
steganographic (imperceptible identifier embedded in audio for
|
|
567
|
+
ownership / forensic tracking) and is owned by ticket I20
|
|
568
|
+
(Trello omiCq7Vn). `audio_overlay` is industry "audio overlay"
|
|
569
|
+
/ "audio branding".
|
|
570
|
+
|
|
571
|
+
Per ADR-0004 + I19 (Trello Xr3Z4GBF).
|
|
572
|
+
parameters:
|
|
573
|
+
env:
|
|
574
|
+
description: Environment (local, stg, prod)
|
|
575
|
+
region:
|
|
576
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
577
|
+
messages:
|
|
578
|
+
operationRequest:
|
|
579
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
580
|
+
|
|
581
|
+
opsAudioWatermark:
|
|
582
|
+
address: gisl-{env}-{region}-ops-audio-watermark
|
|
583
|
+
description: |
|
|
584
|
+
SQS queue for audio_watermark operations (steganographic
|
|
585
|
+
forensic watermarking — Cinavia / Resemble PerTh territory).
|
|
586
|
+
Subscribed to the `operations` SNS topic with filter
|
|
587
|
+
`operation_type = audio_watermark`. Single-input.
|
|
588
|
+
|
|
589
|
+
Both mime_groups (`audio`, `video` — embed in video's audio
|
|
590
|
+
track) are `availability: planned` + `required_tier:
|
|
591
|
+
enterprise` per the operation schema; the API rejects workflow-
|
|
592
|
+
create with `feature_not_available` (422) until the Lambda
|
|
593
|
+
ships, plus 403 `feature_tier_restricted` for non-enterprise
|
|
594
|
+
callers, so traffic does not reach this queue today. Backed
|
|
595
|
+
by the `operation-audio-watermark` Lambda (cross-repo follow-up;
|
|
596
|
+
not yet shipped).
|
|
597
|
+
|
|
598
|
+
**Industry naming.** This is *audio watermarking* (steganographic
|
|
599
|
+
ownership / forensic tracking), NOT *audio overlay* (audible
|
|
600
|
+
mixing). Audio overlay is owned by `audio_overlay` (I19).
|
|
601
|
+
|
|
602
|
+
Pairs with `POST /api/audio-watermark/decode` for
|
|
603
|
+
own-watermarks-only extraction (declared in `openapi/api.yaml`).
|
|
604
|
+
|
|
605
|
+
Per ADR-0004 + I20 (Trello omiCq7Vn).
|
|
606
|
+
parameters:
|
|
607
|
+
env:
|
|
608
|
+
description: Environment (local, stg, prod)
|
|
609
|
+
region:
|
|
610
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
611
|
+
messages:
|
|
612
|
+
operationRequest:
|
|
613
|
+
$ref: '#/components/messages/OperationRequestMessage'
|
|
614
|
+
|
|
615
|
+
# ============================================
|
|
616
|
+
# OPS FAMILY - DEAD LETTER QUEUES
|
|
617
|
+
# ============================================
|
|
618
|
+
|
|
619
|
+
opsThumbnailDlq:
|
|
620
|
+
address: gisl-{env}-{region}-ops-thumbnail-dlq
|
|
621
|
+
description: DLQ for failed legacy thumbnail operations. Messages land here after 5 failed processing attempts.
|
|
622
|
+
parameters:
|
|
623
|
+
env:
|
|
624
|
+
description: Environment (local, stg, prod)
|
|
625
|
+
region:
|
|
626
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
627
|
+
|
|
628
|
+
opsThumbnailImageDlq:
|
|
629
|
+
address: gisl-{env}-{region}-ops-thumbnail-image-dlq
|
|
630
|
+
description: DLQ for failed image thumbnail operations. Messages land here after 5 failed processing attempts.
|
|
631
|
+
parameters:
|
|
632
|
+
env:
|
|
633
|
+
description: Environment (local, stg, prod)
|
|
634
|
+
region:
|
|
635
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
636
|
+
|
|
637
|
+
opsThumbnailVideoDlq:
|
|
638
|
+
address: gisl-{env}-{region}-ops-thumbnail-video-dlq
|
|
639
|
+
description: DLQ for failed video thumbnail operations. Messages land here after 5 failed processing attempts.
|
|
640
|
+
parameters:
|
|
641
|
+
env:
|
|
642
|
+
description: Environment (local, stg, prod)
|
|
643
|
+
region:
|
|
644
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
645
|
+
|
|
646
|
+
opsThumbnailDocumentDlq:
|
|
647
|
+
address: gisl-{env}-{region}-ops-thumbnail-document-dlq
|
|
648
|
+
description: DLQ for failed document thumbnail operations. Messages land here after 5 failed processing attempts.
|
|
649
|
+
parameters:
|
|
650
|
+
env:
|
|
651
|
+
description: Environment (local, stg, prod)
|
|
652
|
+
region:
|
|
653
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
654
|
+
|
|
655
|
+
opsThumbnailOfficeDlq:
|
|
656
|
+
address: gisl-{env}-{region}-ops-thumbnail-office-dlq
|
|
657
|
+
description: DLQ for failed office thumbnail operations. Messages land here after 5 failed processing attempts.
|
|
658
|
+
parameters:
|
|
659
|
+
env:
|
|
660
|
+
description: Environment (local, stg, prod)
|
|
661
|
+
region:
|
|
662
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
663
|
+
|
|
664
|
+
opsImageWatermarkDlq:
|
|
665
|
+
address: gisl-{env}-{region}-ops-image-watermark-dlq
|
|
666
|
+
description: DLQ for failed image_watermark operations. Messages land here after 5 failed processing attempts.
|
|
667
|
+
parameters:
|
|
668
|
+
env:
|
|
669
|
+
description: Environment (local, stg, prod)
|
|
670
|
+
region:
|
|
671
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
672
|
+
|
|
673
|
+
opsTextWatermarkDlq:
|
|
674
|
+
address: gisl-{env}-{region}-ops-text-watermark-dlq
|
|
675
|
+
description: DLQ for failed text_watermark operations. Messages land here after 5 failed processing attempts.
|
|
676
|
+
parameters:
|
|
677
|
+
env:
|
|
678
|
+
description: Environment (local, stg, prod)
|
|
679
|
+
region:
|
|
680
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
681
|
+
|
|
682
|
+
opsMergeDlq:
|
|
683
|
+
address: gisl-{env}-{region}-ops-merge-dlq
|
|
684
|
+
description: DLQ for failed merge operations. Messages land here after 5 failed processing attempts.
|
|
685
|
+
parameters:
|
|
686
|
+
env:
|
|
687
|
+
description: Environment (local, stg, prod)
|
|
688
|
+
region:
|
|
689
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
690
|
+
|
|
691
|
+
opsArchiveDlq:
|
|
692
|
+
address: gisl-{env}-{region}-ops-archive-dlq
|
|
693
|
+
description: DLQ for failed archive operations. Messages land here after 5 failed processing attempts.
|
|
694
|
+
parameters:
|
|
695
|
+
env:
|
|
696
|
+
description: Environment (local, stg, prod)
|
|
697
|
+
region:
|
|
698
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
699
|
+
|
|
700
|
+
opsConvertDlq:
|
|
701
|
+
address: gisl-{env}-{region}-ops-convert-dlq
|
|
702
|
+
description: DLQ for failed convert operations. Messages land here after 5 failed processing attempts.
|
|
703
|
+
parameters:
|
|
704
|
+
env:
|
|
705
|
+
description: Environment (local, stg, prod)
|
|
706
|
+
region:
|
|
707
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
708
|
+
|
|
709
|
+
opsCustomLumaDlq:
|
|
710
|
+
address: gisl-{env}-{region}-ops-custom-luma-dlq
|
|
711
|
+
description: |
|
|
712
|
+
DLQ for failed custom_luma operations (per ticket I29).
|
|
713
|
+
Messages land here after 5 failed processing attempts. No traffic
|
|
714
|
+
reaches this queue while custom_luma is `availability: planned`.
|
|
715
|
+
parameters:
|
|
716
|
+
env:
|
|
717
|
+
description: Environment (local, stg, prod)
|
|
718
|
+
region:
|
|
719
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
720
|
+
|
|
721
|
+
opsAudioOverlayDlq:
|
|
722
|
+
address: gisl-{env}-{region}-ops-audio-overlay-dlq
|
|
723
|
+
description: |
|
|
724
|
+
DLQ for failed audio_overlay operations (per ticket I19).
|
|
725
|
+
Messages land here after 5 failed processing attempts. No
|
|
726
|
+
traffic reaches this queue while audio_overlay is
|
|
727
|
+
`availability: planned`.
|
|
728
|
+
parameters:
|
|
729
|
+
env:
|
|
730
|
+
description: Environment (local, stg, prod)
|
|
731
|
+
region:
|
|
732
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
733
|
+
|
|
734
|
+
opsAudioWatermarkDlq:
|
|
735
|
+
address: gisl-{env}-{region}-ops-audio-watermark-dlq
|
|
736
|
+
description: |
|
|
737
|
+
DLQ for failed audio_watermark operations (per ticket I20).
|
|
738
|
+
Messages land here after 5 failed processing attempts. No
|
|
739
|
+
traffic reaches this queue while audio_watermark is
|
|
740
|
+
`availability: planned` + `required_tier: enterprise`.
|
|
741
|
+
parameters:
|
|
742
|
+
env:
|
|
743
|
+
description: Environment (local, stg, prod)
|
|
744
|
+
region:
|
|
745
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
746
|
+
|
|
747
|
+
# ============================================
|
|
748
|
+
# UPLOAD PROBE (per ticket vBlEurU7 + M2 Epic SrHwuvIl)
|
|
749
|
+
# ============================================
|
|
750
|
+
|
|
751
|
+
uploadProbeRequestsTopic:
|
|
752
|
+
address: gisl-{env}-{region}-upload-probe-requests
|
|
753
|
+
description: |
|
|
754
|
+
SNS topic where the API publishes asynchronous upload-probe
|
|
755
|
+
requests for eager `rich_metadata` enrichment on upload finalize.
|
|
756
|
+
Per ticket [vBlEurU7](https://trello.com/c/vBlEurU7) +
|
|
757
|
+
M2 Epic re-scope ([SrHwuvIl](https://trello.com/c/SrHwuvIl)).
|
|
758
|
+
|
|
759
|
+
The probe Lambda ([rdBHmTfa](https://trello.com/c/rdBHmTfa))
|
|
760
|
+
can be invoked two ways with the same `UploadProbeRequest`
|
|
761
|
+
payload shape:
|
|
762
|
+
|
|
763
|
+
1. **Synchronous AWS Lambda Invoke** (RequestResponse mode) —
|
|
764
|
+
used to back `POST /api/uploads/{id}/probe`. Not modelled
|
|
765
|
+
as an AsyncAPI channel; the request payload + the response
|
|
766
|
+
payload (`UploadProbeResponse` from `openapi/api.yaml`) are
|
|
767
|
+
the contract for that path.
|
|
768
|
+
2. **Asynchronous SNS -> SQS -> Lambda** — used by the upload
|
|
769
|
+
finalize publisher. This topic is the entry point for that
|
|
770
|
+
async branch. The Lambda then publishes the result to the
|
|
771
|
+
`uploadProbeCompletionsQueue` for the API consumer to read.
|
|
772
|
+
|
|
773
|
+
No SNS message attribute filter is applied — the topic has a
|
|
774
|
+
single subscription (`uploadProbeQueue`) and the Lambda accepts
|
|
775
|
+
every probe request published here.
|
|
776
|
+
parameters:
|
|
777
|
+
env:
|
|
778
|
+
description: Environment (local, stg, prod)
|
|
779
|
+
region:
|
|
780
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
781
|
+
messages:
|
|
782
|
+
uploadProbeRequest:
|
|
783
|
+
$ref: '#/components/messages/UploadProbeRequestMessage'
|
|
784
|
+
|
|
785
|
+
uploadProbeQueue:
|
|
786
|
+
address: gisl-{env}-{region}-upload-probe
|
|
787
|
+
description: |
|
|
788
|
+
SQS queue subscribed to the `upload-probe-requests` SNS topic.
|
|
789
|
+
The upload-probe Lambda consumes from this queue.
|
|
790
|
+
|
|
791
|
+
Standard (non-FIFO) — each probe request is independent; no
|
|
792
|
+
ordering guarantees are required across uploads.
|
|
793
|
+
parameters:
|
|
794
|
+
env:
|
|
795
|
+
description: Environment (local, stg, prod)
|
|
796
|
+
region:
|
|
797
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
798
|
+
messages:
|
|
799
|
+
uploadProbeRequest:
|
|
800
|
+
$ref: '#/components/messages/UploadProbeRequestMessage'
|
|
801
|
+
|
|
802
|
+
uploadProbeDlq:
|
|
803
|
+
address: gisl-{env}-{region}-upload-probe-dlq
|
|
804
|
+
description: |
|
|
805
|
+
DLQ for failed upload-probe Lambda invocations from the async
|
|
806
|
+
branch. Messages land here after 5 failed processing attempts.
|
|
807
|
+
The sync `POST /api/uploads/{id}/probe` path does not flow
|
|
808
|
+
through this DLQ — sync errors are surfaced inline via the
|
|
809
|
+
Lambda RequestResponse return value.
|
|
810
|
+
parameters:
|
|
811
|
+
env:
|
|
812
|
+
description: Environment (local, stg, prod)
|
|
813
|
+
region:
|
|
814
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
815
|
+
|
|
816
|
+
uploadProbeCompletionsQueue:
|
|
817
|
+
address: gisl-{env}-{region}-upload-probe-completions
|
|
818
|
+
description: |
|
|
819
|
+
SQS queue where the upload-probe Lambda publishes
|
|
820
|
+
`UploadProbeCompletion` messages on the async branch. The API
|
|
821
|
+
consumer worker reads from this queue and persists
|
|
822
|
+
`rich_metadata` on the upload row.
|
|
823
|
+
|
|
824
|
+
Standard (non-FIFO) — completions are independent; no ordering
|
|
825
|
+
guarantees across uploads. Idempotency is handled by the
|
|
826
|
+
`idempotency_key` field on the message payload (echoed from the
|
|
827
|
+
original request) and by the API consumer's per-upload
|
|
828
|
+
"first-write-wins" persistence path.
|
|
829
|
+
|
|
830
|
+
The sync `POST /api/uploads/{id}/probe` path does not publish
|
|
831
|
+
here — sync results are returned inline via the Lambda
|
|
832
|
+
RequestResponse return value.
|
|
833
|
+
parameters:
|
|
834
|
+
env:
|
|
835
|
+
description: Environment (local, stg, prod)
|
|
836
|
+
region:
|
|
837
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
838
|
+
messages:
|
|
839
|
+
uploadProbeCompletion:
|
|
840
|
+
$ref: '#/components/messages/UploadProbeCompletionMessage'
|
|
841
|
+
|
|
842
|
+
uploadProbeCompletionsDlq:
|
|
843
|
+
address: gisl-{env}-{region}-upload-probe-completions-dlq
|
|
844
|
+
description: |
|
|
845
|
+
DLQ for failed completion-message processing by the API
|
|
846
|
+
consumer worker. Messages land here after 5 failed processing
|
|
847
|
+
attempts (e.g. database persistence failures, malformed
|
|
848
|
+
payloads).
|
|
849
|
+
parameters:
|
|
850
|
+
env:
|
|
851
|
+
description: Environment (local, stg, prod)
|
|
852
|
+
region:
|
|
853
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
854
|
+
|
|
855
|
+
# ============================================
|
|
856
|
+
# NOTIFICATIONS (Lambda -> API)
|
|
857
|
+
# ============================================
|
|
858
|
+
|
|
859
|
+
notificationsOperationsTopic:
|
|
860
|
+
address: gisl-{env}-{region}-notifications-operations.fifo
|
|
861
|
+
description: |
|
|
862
|
+
FIFO SNS topic where Lambdas publish all operation notifications (progress and results).
|
|
863
|
+
API subscribes via FIFO SQS with Raw Message Delivery enabled.
|
|
864
|
+
|
|
865
|
+
**FIFO Publishing Requirements:**
|
|
866
|
+
- MessageGroupId: Use operation_id (ensures ordering per operation)
|
|
867
|
+
- MessageDeduplicationId: Not required (content-based deduplication enabled)
|
|
868
|
+
parameters:
|
|
869
|
+
env:
|
|
870
|
+
description: Environment (local, stg, prod)
|
|
871
|
+
region:
|
|
872
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
873
|
+
messages:
|
|
874
|
+
operationProgress:
|
|
875
|
+
$ref: '#/components/messages/OperationProgressMessage'
|
|
876
|
+
operationResult:
|
|
877
|
+
$ref: '#/components/messages/OperationResultMessage'
|
|
878
|
+
|
|
879
|
+
notificationsOperationsQueue:
|
|
880
|
+
address: gisl-{env}-{region}-notifications-operations.fifo
|
|
881
|
+
description: |
|
|
882
|
+
FIFO SQS queue subscribed to notifications-operations SNS topic.
|
|
883
|
+
Receives both OperationProgress and OperationResult messages.
|
|
884
|
+
Raw Message Delivery enabled (no SNS envelope).
|
|
885
|
+
|
|
886
|
+
FIFO ensures message ordering per operation (operation_id used as MessageGroupId).
|
|
887
|
+
This guarantees OperationProgress messages arrive before OperationResult.
|
|
888
|
+
parameters:
|
|
889
|
+
env:
|
|
890
|
+
description: Environment (local, stg, prod)
|
|
891
|
+
region:
|
|
892
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
893
|
+
messages:
|
|
894
|
+
operationProgress:
|
|
895
|
+
$ref: '#/components/messages/OperationProgressMessage'
|
|
896
|
+
operationResult:
|
|
897
|
+
$ref: '#/components/messages/OperationResultMessage'
|
|
898
|
+
|
|
899
|
+
notificationsOperationsDlq:
|
|
900
|
+
address: gisl-{env}-{region}-notifications-operations-dlq.fifo
|
|
901
|
+
description: DLQ for failed notification processing. Messages land here after 5 failed processing attempts.
|
|
902
|
+
parameters:
|
|
903
|
+
env:
|
|
904
|
+
description: Environment (local, stg, prod)
|
|
905
|
+
region:
|
|
906
|
+
description: AWS region abbreviation (euw1, use1, etc.)
|
|
907
|
+
|
|
908
|
+
operations:
|
|
909
|
+
# ============================================
|
|
910
|
+
# PUBLISH OPERATIONS (API -> SNS)
|
|
911
|
+
# ============================================
|
|
912
|
+
|
|
913
|
+
publishJobRequest:
|
|
914
|
+
action: send
|
|
915
|
+
channel:
|
|
916
|
+
$ref: '#/channels/jobRequestsTopic'
|
|
917
|
+
summary: Publish a compression job request to the job-requests SNS topic.
|
|
918
|
+
description: |
|
|
919
|
+
Compression-branch publisher path. Invoked by the API for any
|
|
920
|
+
operation with `operation_type == compress`, regardless of media
|
|
921
|
+
type. The target SNS topic filters subscriptions on `job_type`
|
|
922
|
+
alone.
|
|
923
|
+
|
|
924
|
+
**Message attribute set on this branch:** `{job_type}` only. The
|
|
925
|
+
publisher does **not** set `operation_type` or `media_group` on
|
|
926
|
+
this branch — the media group is encoded as `job_type` and no
|
|
927
|
+
other attribute is used as a filter on this topic.
|
|
928
|
+
|
|
929
|
+
**`job_type` value derivation:** the API derives `job_type` from
|
|
930
|
+
its `OperationMediaGroupResolver` output
|
|
931
|
+
(`image` | `video` | `audio` | `document`) at publish time.
|
|
932
|
+
|
|
933
|
+
See `info.description` above for the full publisher branching rule.
|
|
934
|
+
messages:
|
|
935
|
+
- $ref: '#/channels/jobRequestsTopic/messages/jobRequest'
|
|
936
|
+
|
|
937
|
+
publishOperationRequest:
|
|
938
|
+
action: send
|
|
939
|
+
channel:
|
|
940
|
+
$ref: '#/channels/operationsTopic'
|
|
941
|
+
summary: Publish a non-compression operation request to the operations SNS topic.
|
|
942
|
+
description: |
|
|
943
|
+
Non-compression-branch publisher path. Invoked by the API for any
|
|
944
|
+
operation where `operation_type != compress` — that is, thumbnail
|
|
945
|
+
(including the four sub-type values during the migration window),
|
|
946
|
+
image_watermark, text_watermark, merge, archive, convert,
|
|
947
|
+
custom_luma, audio_overlay, audio_watermark. The target SNS
|
|
948
|
+
topic filters subscriptions on `operation_type` alone.
|
|
949
|
+
|
|
950
|
+
**Message attributes set on this branch:** `{operation_type,
|
|
951
|
+
media_group}`, with `media_group` omitted for `archive` (which is
|
|
952
|
+
media-agnostic). `operation_type` is the filter attribute;
|
|
953
|
+
`media_group` is informational metadata preserved for consumer
|
|
954
|
+
observability and log correlation and is **not** used by SNS as a
|
|
955
|
+
routing filter.
|
|
956
|
+
|
|
957
|
+
See `info.description` above for the full publisher branching rule.
|
|
958
|
+
messages:
|
|
959
|
+
- $ref: '#/channels/operationsTopic/messages/operationRequest'
|
|
960
|
+
|
|
961
|
+
# ============================================
|
|
962
|
+
# CONSUME OPERATIONS - JOBS FAMILY (COMPRESSION)
|
|
963
|
+
# ============================================
|
|
964
|
+
|
|
965
|
+
consumeImageOperation:
|
|
966
|
+
action: receive
|
|
967
|
+
channel:
|
|
968
|
+
$ref: '#/channels/jobsImage'
|
|
969
|
+
summary: Process image compression job
|
|
970
|
+
description: |
|
|
971
|
+
The image compression Lambda consumes jobs for image inputs.
|
|
972
|
+
Handles `compress` only. Non-compression image operations
|
|
973
|
+
(thumbnail, image_watermark, text_watermark, convert, merge) are
|
|
974
|
+
routed to their respective queues on the ops-family under the
|
|
975
|
+
`operations` topic.
|
|
976
|
+
messages:
|
|
977
|
+
- $ref: '#/channels/jobsImage/messages/jobRequest'
|
|
978
|
+
|
|
979
|
+
consumeVideoOperation:
|
|
980
|
+
action: receive
|
|
981
|
+
channel:
|
|
982
|
+
$ref: '#/channels/jobsVideo'
|
|
983
|
+
summary: Process video compression job
|
|
984
|
+
description: |
|
|
985
|
+
The video compression Lambda consumes jobs for video inputs.
|
|
986
|
+
Handles `compress` only. Non-compression video operations
|
|
987
|
+
(thumbnail, convert, merge) are routed to their respective queues
|
|
988
|
+
on the ops-family under the `operations` topic.
|
|
989
|
+
messages:
|
|
990
|
+
- $ref: '#/channels/jobsVideo/messages/jobRequest'
|
|
991
|
+
|
|
992
|
+
consumeAudioOperation:
|
|
993
|
+
action: receive
|
|
994
|
+
channel:
|
|
995
|
+
$ref: '#/channels/jobsAudio'
|
|
996
|
+
summary: Process audio compression job
|
|
997
|
+
description: |
|
|
998
|
+
The audio compression Lambda consumes jobs for audio inputs.
|
|
999
|
+
Handles `compress` only. Non-compression audio operations
|
|
1000
|
+
(convert, merge) are routed to their respective queues on the
|
|
1001
|
+
ops-family under the `operations` topic.
|
|
1002
|
+
messages:
|
|
1003
|
+
- $ref: '#/channels/jobsAudio/messages/jobRequest'
|
|
1004
|
+
|
|
1005
|
+
consumeDocumentOperation:
|
|
1006
|
+
action: receive
|
|
1007
|
+
channel:
|
|
1008
|
+
$ref: '#/channels/jobsDocument'
|
|
1009
|
+
summary: Process document compression job
|
|
1010
|
+
description: |
|
|
1011
|
+
The document compression Lambda consumes jobs for document inputs.
|
|
1012
|
+
Handles `compress` only. Non-compression document operations
|
|
1013
|
+
(thumbnail, convert, merge) are routed to their respective queues
|
|
1014
|
+
on the ops-family under the `operations` topic.
|
|
1015
|
+
messages:
|
|
1016
|
+
- $ref: '#/channels/jobsDocument/messages/jobRequest'
|
|
1017
|
+
|
|
1018
|
+
# ============================================
|
|
1019
|
+
# CONSUME OPERATIONS - OPS FAMILY (NON-COMPRESSION)
|
|
1020
|
+
# ============================================
|
|
1021
|
+
|
|
1022
|
+
consumeThumbnailOperation:
|
|
1023
|
+
action: receive
|
|
1024
|
+
channel:
|
|
1025
|
+
$ref: '#/channels/opsThumbnail'
|
|
1026
|
+
summary: Process legacy thumbnail operation
|
|
1027
|
+
description: |
|
|
1028
|
+
The legacy thumbnail Lambda consumes thumbnail requests routed
|
|
1029
|
+
by `operation_type=thumbnail`. Handles thumbnail generation for
|
|
1030
|
+
all media types in a single Lambda. This is the current live
|
|
1031
|
+
routing target for the API publisher; it will be retired after
|
|
1032
|
+
the publisher adopts the four sub-type values.
|
|
1033
|
+
messages:
|
|
1034
|
+
- $ref: '#/channels/opsThumbnail/messages/operationRequest'
|
|
1035
|
+
|
|
1036
|
+
consumeThumbnailImageOperation:
|
|
1037
|
+
action: receive
|
|
1038
|
+
channel:
|
|
1039
|
+
$ref: '#/channels/opsThumbnailImage'
|
|
1040
|
+
summary: Process image thumbnail operation
|
|
1041
|
+
description: |
|
|
1042
|
+
The image thumbnail Lambda consumes thumbnail requests routed by
|
|
1043
|
+
`operation_type=thumbnail_image`. Backed by a Rust image crate.
|
|
1044
|
+
Not yet receiving traffic — see channel description.
|
|
1045
|
+
messages:
|
|
1046
|
+
- $ref: '#/channels/opsThumbnailImage/messages/operationRequest'
|
|
1047
|
+
|
|
1048
|
+
consumeThumbnailVideoOperation:
|
|
1049
|
+
action: receive
|
|
1050
|
+
channel:
|
|
1051
|
+
$ref: '#/channels/opsThumbnailVideo'
|
|
1052
|
+
summary: Process video thumbnail operation
|
|
1053
|
+
description: |
|
|
1054
|
+
The video thumbnail Lambda consumes thumbnail requests routed by
|
|
1055
|
+
`operation_type=thumbnail_video`. Backed by FFmpeg. Not yet
|
|
1056
|
+
receiving traffic — see channel description.
|
|
1057
|
+
messages:
|
|
1058
|
+
- $ref: '#/channels/opsThumbnailVideo/messages/operationRequest'
|
|
1059
|
+
|
|
1060
|
+
consumeThumbnailDocumentOperation:
|
|
1061
|
+
action: receive
|
|
1062
|
+
channel:
|
|
1063
|
+
$ref: '#/channels/opsThumbnailDocument'
|
|
1064
|
+
summary: Process document thumbnail operation
|
|
1065
|
+
description: |
|
|
1066
|
+
The document (PDF/EPUB) thumbnail Lambda consumes thumbnail
|
|
1067
|
+
requests routed by `operation_type=thumbnail_document`. Backed by
|
|
1068
|
+
Ghostscript. Not yet receiving traffic — see channel description.
|
|
1069
|
+
messages:
|
|
1070
|
+
- $ref: '#/channels/opsThumbnailDocument/messages/operationRequest'
|
|
1071
|
+
|
|
1072
|
+
consumeThumbnailOfficeOperation:
|
|
1073
|
+
action: receive
|
|
1074
|
+
channel:
|
|
1075
|
+
$ref: '#/channels/opsThumbnailOffice'
|
|
1076
|
+
summary: Process office document thumbnail operation
|
|
1077
|
+
description: |
|
|
1078
|
+
The office document (DOCX/XLSX/PPTX/ODT/ODS/ODP) thumbnail Lambda
|
|
1079
|
+
consumes thumbnail requests routed by
|
|
1080
|
+
`operation_type=thumbnail_office`. Backed by LibreOffice. Not yet
|
|
1081
|
+
receiving traffic — see channel description.
|
|
1082
|
+
messages:
|
|
1083
|
+
- $ref: '#/channels/opsThumbnailOffice/messages/operationRequest'
|
|
1084
|
+
|
|
1085
|
+
consumeImageWatermarkOperation:
|
|
1086
|
+
action: receive
|
|
1087
|
+
channel:
|
|
1088
|
+
$ref: '#/channels/opsImageWatermark'
|
|
1089
|
+
summary: Process image_watermark operation
|
|
1090
|
+
description: |
|
|
1091
|
+
The operation-image-watermark Lambda consumes image_watermark
|
|
1092
|
+
requests routed by `operation_type=image_watermark`. Multi-input
|
|
1093
|
+
(Path B with role: base + overlay per JobInputV2.role).
|
|
1094
|
+
|
|
1095
|
+
Stable for image bases today; animated GIF (`image_gif` group) and
|
|
1096
|
+
video bases (`video` group) are advertised as `planned` in the
|
|
1097
|
+
schema (I5 — Trello AKZiOXnd) and dispatch returns
|
|
1098
|
+
`feature_not_available` (422) at the API edge until Lambda support
|
|
1099
|
+
ships. Per ADR-0004 + I4-CONS + I5.
|
|
1100
|
+
messages:
|
|
1101
|
+
- $ref: '#/channels/opsImageWatermark/messages/operationRequest'
|
|
1102
|
+
|
|
1103
|
+
consumeTextWatermarkOperation:
|
|
1104
|
+
action: receive
|
|
1105
|
+
channel:
|
|
1106
|
+
$ref: '#/channels/opsTextWatermark'
|
|
1107
|
+
summary: Process text_watermark operation
|
|
1108
|
+
description: |
|
|
1109
|
+
The operation-text-watermark Lambda consumes text_watermark
|
|
1110
|
+
requests routed by `operation_type=text_watermark`. Single-input;
|
|
1111
|
+
image-only. Renders text via bundled Liberation Sans (SIL OFL),
|
|
1112
|
+
supports `single` and `tiled` watermark_mode. Per ADR-0004 + I4-CONS.
|
|
1113
|
+
messages:
|
|
1114
|
+
- $ref: '#/channels/opsTextWatermark/messages/operationRequest'
|
|
1115
|
+
|
|
1116
|
+
consumeMergeOperation:
|
|
1117
|
+
action: receive
|
|
1118
|
+
channel:
|
|
1119
|
+
$ref: '#/channels/opsMerge'
|
|
1120
|
+
summary: Process merge operation
|
|
1121
|
+
description: |
|
|
1122
|
+
The merge Lambda consumes merge requests routed by
|
|
1123
|
+
`operation_type=merge`. A single Lambda handles the supported merge
|
|
1124
|
+
output types (animated GIF, video slideshow/concat, audio concat).
|
|
1125
|
+
The `output_type` field on the request determines the encoding
|
|
1126
|
+
path internally. Image collage and PDF concatenation are not
|
|
1127
|
+
supported by the V1 Lambda.
|
|
1128
|
+
messages:
|
|
1129
|
+
- $ref: '#/channels/opsMerge/messages/operationRequest'
|
|
1130
|
+
|
|
1131
|
+
consumeArchiveOperation:
|
|
1132
|
+
action: receive
|
|
1133
|
+
channel:
|
|
1134
|
+
$ref: '#/channels/opsArchive'
|
|
1135
|
+
summary: Process archive operation
|
|
1136
|
+
description: |
|
|
1137
|
+
The archive Lambda consumes archive requests routed by
|
|
1138
|
+
`operation_type=archive`. Media-agnostic: bundles files of any
|
|
1139
|
+
type into ZIP/tar.gz.
|
|
1140
|
+
messages:
|
|
1141
|
+
- $ref: '#/channels/opsArchive/messages/operationRequest'
|
|
1142
|
+
|
|
1143
|
+
consumeConvertOperation:
|
|
1144
|
+
action: receive
|
|
1145
|
+
channel:
|
|
1146
|
+
$ref: '#/channels/opsConvert'
|
|
1147
|
+
summary: Process convert operation
|
|
1148
|
+
description: |
|
|
1149
|
+
The convert Lambda consumes convert requests routed by
|
|
1150
|
+
`operation_type=convert`. Handles format conversion across all
|
|
1151
|
+
media types (image, video, audio, document).
|
|
1152
|
+
messages:
|
|
1153
|
+
- $ref: '#/channels/opsConvert/messages/operationRequest'
|
|
1154
|
+
|
|
1155
|
+
consumeCustomLumaOperation:
|
|
1156
|
+
action: receive
|
|
1157
|
+
channel:
|
|
1158
|
+
$ref: '#/channels/opsCustomLuma'
|
|
1159
|
+
summary: Process custom_luma operation
|
|
1160
|
+
description: |
|
|
1161
|
+
The `operation-custom-luma` Lambda (cross-repo follow-up — not
|
|
1162
|
+
yet shipped) consumes custom_luma requests routed by
|
|
1163
|
+
`operation_type=custom_luma`. Multi-input (Path B with
|
|
1164
|
+
`role: base` + `role: transition_mask` per `JobInputV2.role`).
|
|
1165
|
+
`availability: planned` + `required_tier: pro`; the API rejects
|
|
1166
|
+
workflow-create with `feature_not_available` (422) until the
|
|
1167
|
+
Lambda ships, so traffic does not reach this channel today.
|
|
1168
|
+
Per ADR-0004 + I29 (Trello EPUE5Vs1).
|
|
1169
|
+
messages:
|
|
1170
|
+
- $ref: '#/channels/opsCustomLuma/messages/operationRequest'
|
|
1171
|
+
|
|
1172
|
+
consumeAudioOverlayOperation:
|
|
1173
|
+
action: receive
|
|
1174
|
+
channel:
|
|
1175
|
+
$ref: '#/channels/opsAudioOverlay'
|
|
1176
|
+
summary: Process audio_overlay operation
|
|
1177
|
+
description: |
|
|
1178
|
+
The `operation-audio-overlay` Lambda (cross-repo follow-up —
|
|
1179
|
+
not yet shipped) consumes audio_overlay requests routed by
|
|
1180
|
+
`operation_type=audio_overlay`. Multi-input (Path B with
|
|
1181
|
+
`role: base` + `role: overlay` per `JobInputV2.role`).
|
|
1182
|
+
Both mime_groups (`audio`, `video`) are `availability: planned`;
|
|
1183
|
+
the API rejects workflow-create with `feature_not_available`
|
|
1184
|
+
(422) until the Lambda ships, so traffic does not reach this
|
|
1185
|
+
channel today.
|
|
1186
|
+
Per ADR-0004 + I19 (Trello Xr3Z4GBF).
|
|
1187
|
+
messages:
|
|
1188
|
+
- $ref: '#/channels/opsAudioOverlay/messages/operationRequest'
|
|
1189
|
+
|
|
1190
|
+
consumeAudioWatermarkOperation:
|
|
1191
|
+
action: receive
|
|
1192
|
+
channel:
|
|
1193
|
+
$ref: '#/channels/opsAudioWatermark'
|
|
1194
|
+
summary: Process audio_watermark operation
|
|
1195
|
+
description: |
|
|
1196
|
+
The `operation-audio-watermark` Lambda (cross-repo follow-up —
|
|
1197
|
+
not yet shipped) consumes audio_watermark requests routed by
|
|
1198
|
+
`operation_type=audio_watermark`. Single-input. Both mime_groups
|
|
1199
|
+
(`audio`, `video`) are `availability: planned` +
|
|
1200
|
+
`required_tier: enterprise`; the API rejects workflow-create
|
|
1201
|
+
with `feature_not_available` (422) until the Lambda ships, plus
|
|
1202
|
+
403 `feature_tier_restricted` for non-enterprise callers, so
|
|
1203
|
+
traffic does not reach this channel today.
|
|
1204
|
+
Per ADR-0004 + I20 (Trello omiCq7Vn).
|
|
1205
|
+
messages:
|
|
1206
|
+
- $ref: '#/channels/opsAudioWatermark/messages/operationRequest'
|
|
1207
|
+
|
|
1208
|
+
# ============================================
|
|
1209
|
+
# NOTIFICATION OPERATIONS
|
|
1210
|
+
# ============================================
|
|
1211
|
+
|
|
1212
|
+
publishOperationProgress:
|
|
1213
|
+
action: send
|
|
1214
|
+
channel:
|
|
1215
|
+
$ref: '#/channels/notificationsOperationsTopic'
|
|
1216
|
+
summary: Publish operation progress update
|
|
1217
|
+
description: |
|
|
1218
|
+
Lambda publishes progress updates during operation processing.
|
|
1219
|
+
These are lightweight messages for real-time status tracking.
|
|
1220
|
+
messages:
|
|
1221
|
+
- $ref: '#/channels/notificationsOperationsTopic/messages/operationProgress'
|
|
1222
|
+
|
|
1223
|
+
publishOperationResult:
|
|
1224
|
+
action: send
|
|
1225
|
+
channel:
|
|
1226
|
+
$ref: '#/channels/notificationsOperationsTopic'
|
|
1227
|
+
summary: Publish operation result
|
|
1228
|
+
description: |
|
|
1229
|
+
Lambda publishes the final result when operation completes or fails.
|
|
1230
|
+
This is a terminal message with full details.
|
|
1231
|
+
messages:
|
|
1232
|
+
- $ref: '#/channels/notificationsOperationsTopic/messages/operationResult'
|
|
1233
|
+
|
|
1234
|
+
consumeOperationNotifications:
|
|
1235
|
+
action: receive
|
|
1236
|
+
channel:
|
|
1237
|
+
$ref: '#/channels/notificationsOperationsQueue'
|
|
1238
|
+
summary: Consume operation notifications
|
|
1239
|
+
description: |
|
|
1240
|
+
API worker consumes both progress and result notifications from SQS.
|
|
1241
|
+
- OperationProgress: Update Redis cache for real-time status (forwarded to frontend via SSE)
|
|
1242
|
+
- OperationResult: Update database Operation entity, derive Job/Workflow status
|
|
1243
|
+
messages:
|
|
1244
|
+
- $ref: '#/channels/notificationsOperationsQueue/messages/operationProgress'
|
|
1245
|
+
- $ref: '#/channels/notificationsOperationsQueue/messages/operationResult'
|
|
1246
|
+
|
|
1247
|
+
# ============================================
|
|
1248
|
+
# UPLOAD-PROBE OPERATIONS (per ticket vBlEurU7)
|
|
1249
|
+
# ============================================
|
|
1250
|
+
|
|
1251
|
+
publishUploadProbeRequest:
|
|
1252
|
+
action: send
|
|
1253
|
+
channel:
|
|
1254
|
+
$ref: '#/channels/uploadProbeRequestsTopic'
|
|
1255
|
+
summary: Publish an async upload-probe request
|
|
1256
|
+
description: |
|
|
1257
|
+
The API publishes to this topic on the **async branch** —
|
|
1258
|
+
typically from the upload-finalize publisher when eager
|
|
1259
|
+
`rich_metadata` enrichment is configured for the caller's
|
|
1260
|
+
tier / MIME group.
|
|
1261
|
+
|
|
1262
|
+
The `POST /api/uploads/{id}/probe` sync path does **not** use
|
|
1263
|
+
this operation — it invokes the Lambda directly via the AWS
|
|
1264
|
+
Lambda Invoke API (RequestResponse mode). The two paths share
|
|
1265
|
+
the `UploadProbeRequest` payload schema so the Lambda accepts
|
|
1266
|
+
a single request shape regardless of invocation source.
|
|
1267
|
+
messages:
|
|
1268
|
+
- $ref: '#/channels/uploadProbeRequestsTopic/messages/uploadProbeRequest'
|
|
1269
|
+
|
|
1270
|
+
consumeUploadProbeRequest:
|
|
1271
|
+
action: receive
|
|
1272
|
+
channel:
|
|
1273
|
+
$ref: '#/channels/uploadProbeQueue'
|
|
1274
|
+
summary: Consume an upload-probe request (async branch)
|
|
1275
|
+
description: |
|
|
1276
|
+
The upload-probe Lambda consumes from the SQS queue subscribed
|
|
1277
|
+
to the `upload-probe-requests` topic. On success the Lambda
|
|
1278
|
+
publishes an `UploadProbeCompletion` to the completions queue;
|
|
1279
|
+
on failure the Lambda emits a completion with `error_code`
|
|
1280
|
+
populated (so the API consumer can persist the failure mode)
|
|
1281
|
+
before SQS retry / DLQ handling kicks in.
|
|
1282
|
+
|
|
1283
|
+
Sync invocations bypass this operation entirely.
|
|
1284
|
+
messages:
|
|
1285
|
+
- $ref: '#/channels/uploadProbeQueue/messages/uploadProbeRequest'
|
|
1286
|
+
|
|
1287
|
+
publishUploadProbeCompletion:
|
|
1288
|
+
action: send
|
|
1289
|
+
channel:
|
|
1290
|
+
$ref: '#/channels/uploadProbeCompletionsQueue'
|
|
1291
|
+
summary: Publish an upload-probe completion (async branch)
|
|
1292
|
+
description: |
|
|
1293
|
+
The upload-probe Lambda publishes the result of the async
|
|
1294
|
+
branch to this queue. The payload shape is `UploadProbeCompletion`
|
|
1295
|
+
and intentionally carries both the success fields
|
|
1296
|
+
(`probe_status`, `media_metadata`, `processing_class_pre_assignment`)
|
|
1297
|
+
and the failure fields (`error_code`, `error_message`) so the
|
|
1298
|
+
API consumer worker handles both outcomes from a single
|
|
1299
|
+
message shape.
|
|
1300
|
+
|
|
1301
|
+
The sync `POST /api/uploads/{id}/probe` path does not publish
|
|
1302
|
+
here — sync results are returned inline via the Lambda
|
|
1303
|
+
RequestResponse return value as `UploadProbeResponse`
|
|
1304
|
+
(`openapi/api.yaml`).
|
|
1305
|
+
messages:
|
|
1306
|
+
- $ref: '#/channels/uploadProbeCompletionsQueue/messages/uploadProbeCompletion'
|
|
1307
|
+
|
|
1308
|
+
consumeUploadProbeCompletion:
|
|
1309
|
+
action: receive
|
|
1310
|
+
channel:
|
|
1311
|
+
$ref: '#/channels/uploadProbeCompletionsQueue'
|
|
1312
|
+
summary: Consume an upload-probe completion (async branch)
|
|
1313
|
+
description: |
|
|
1314
|
+
The API consumer worker reads completions from this queue and
|
|
1315
|
+
persists `rich_metadata` (and any error state) on the upload
|
|
1316
|
+
row. Idempotency is handled by the `idempotency_key` echoed in
|
|
1317
|
+
the completion payload plus a per-upload "first-write-wins"
|
|
1318
|
+
persistence path on the API side.
|
|
1319
|
+
messages:
|
|
1320
|
+
- $ref: '#/channels/uploadProbeCompletionsQueue/messages/uploadProbeCompletion'
|
|
1321
|
+
|
|
1322
|
+
components:
|
|
1323
|
+
messages:
|
|
1324
|
+
# ============================================
|
|
1325
|
+
# JOB REQUEST MESSAGE (compression branch)
|
|
1326
|
+
# ============================================
|
|
1327
|
+
|
|
1328
|
+
JobRequestMessage:
|
|
1329
|
+
name: JobRequest
|
|
1330
|
+
title: Compression Job Request
|
|
1331
|
+
summary: Request to process a compression operation
|
|
1332
|
+
description: |
|
|
1333
|
+
Message sent by the API to request processing of a **compression**
|
|
1334
|
+
operation. Published to the `job-requests` SNS topic; routed by the
|
|
1335
|
+
single-attribute filter `job_type` to one of the four
|
|
1336
|
+
per-media-type compression queues.
|
|
1337
|
+
|
|
1338
|
+
**SNS Message Attributes (routing):**
|
|
1339
|
+
- `job_type`: always present. Values: `image`, `video`, `audio`,
|
|
1340
|
+
`document`. Used by SNS as the filter attribute on the
|
|
1341
|
+
`job-requests` topic.
|
|
1342
|
+
|
|
1343
|
+
No other message attributes are set on this branch by the API
|
|
1344
|
+
publisher. `operation_type` and `media_group` are **not** set —
|
|
1345
|
+
the media group is encoded as `job_type`.
|
|
1346
|
+
|
|
1347
|
+
**Payload:** uses the shared `OperationRequest` schema. For
|
|
1348
|
+
compression, `operation_type` inside the payload is always
|
|
1349
|
+
`compress`, `file_type` is set to the input MIME, and the
|
|
1350
|
+
`source_bucket` / `source_key` fields identify the input.
|
|
1351
|
+
contentType: application/json
|
|
1352
|
+
headers:
|
|
1353
|
+
$ref: '#/components/schemas/JobRequestAttributes'
|
|
1354
|
+
payload:
|
|
1355
|
+
$ref: '#/components/schemas/OperationRequest'
|
|
1356
|
+
examples:
|
|
1357
|
+
- name: Image Compression
|
|
1358
|
+
summary: Compress a PNG image with lossy mode
|
|
1359
|
+
headers:
|
|
1360
|
+
job_type: "image"
|
|
1361
|
+
payload:
|
|
1362
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
1363
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
1364
|
+
operation_type: "compress"
|
|
1365
|
+
file_type: "image/png"
|
|
1366
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1367
|
+
source_key: "uploads/018f9c42-aabb/photo.png"
|
|
1368
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1369
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e112/018f9c42-5d6b-7481-b3df-9fd0a0a5e200/"
|
|
1370
|
+
options:
|
|
1371
|
+
mode: "lossy"
|
|
1372
|
+
quality: 80
|
|
1373
|
+
metadata: "copyright"
|
|
1374
|
+
- name: Video Compression
|
|
1375
|
+
summary: Compress an MP4 video
|
|
1376
|
+
headers:
|
|
1377
|
+
job_type: "video"
|
|
1378
|
+
payload:
|
|
1379
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e113"
|
|
1380
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e201"
|
|
1381
|
+
operation_type: "compress"
|
|
1382
|
+
file_type: "video/mp4"
|
|
1383
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1384
|
+
source_key: "uploads/018f9c42-ccdd/video.mp4"
|
|
1385
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1386
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e113/018f9c42-5d6b-7481-b3df-9fd0a0a5e201/"
|
|
1387
|
+
options:
|
|
1388
|
+
codec: "h265"
|
|
1389
|
+
crf: 28
|
|
1390
|
+
preset: "medium"
|
|
1391
|
+
|
|
1392
|
+
# ============================================
|
|
1393
|
+
# OPERATION REQUEST MESSAGE (non-compression branch)
|
|
1394
|
+
# ============================================
|
|
1395
|
+
|
|
1396
|
+
OperationRequestMessage:
|
|
1397
|
+
name: OperationRequest
|
|
1398
|
+
title: Non-Compression Operation Request
|
|
1399
|
+
summary: Request to process a non-compression operation
|
|
1400
|
+
description: |
|
|
1401
|
+
Message sent by the API to request processing of any
|
|
1402
|
+
**non-compression** operation (thumbnail, image_watermark,
|
|
1403
|
+
text_watermark, merge, archive, convert, custom_luma,
|
|
1404
|
+
audio_overlay, audio_watermark). Published to the
|
|
1405
|
+
`operations` SNS topic; routed by the single-attribute filter
|
|
1406
|
+
`operation_type` to one of the ops-family queues.
|
|
1407
|
+
|
|
1408
|
+
**SNS Message Attributes:**
|
|
1409
|
+
- `operation_type`: always present. Values: `thumbnail`,
|
|
1410
|
+
`thumbnail_image`, `thumbnail_video`, `thumbnail_document`,
|
|
1411
|
+
`thumbnail_office`, `image_watermark`, `text_watermark`,
|
|
1412
|
+
`merge`, `archive`, `convert`, `custom_luma`,
|
|
1413
|
+
`audio_overlay`, `audio_watermark`. Used by SNS as the
|
|
1414
|
+
filter attribute on the `operations` topic.
|
|
1415
|
+
- `media_group`: informational metadata, present for every
|
|
1416
|
+
operation except `archive` (which is media-agnostic). Values:
|
|
1417
|
+
`image`, `video`, `audio`, `document`. **Not** used by SNS as
|
|
1418
|
+
a routing filter — preserved for consumer observability and
|
|
1419
|
+
log correlation.
|
|
1420
|
+
|
|
1421
|
+
**Input models:**
|
|
1422
|
+
- Single-input operations (thumbnail, text_watermark, convert,
|
|
1423
|
+
audio_watermark): use `source_bucket` + `source_key`.
|
|
1424
|
+
`file_type` required. For `thumbnail`, the SNS
|
|
1425
|
+
`operation_type` attribute is permitted to carry a per-media
|
|
1426
|
+
sub-type value for routing (see `OperationRequestAttributes`
|
|
1427
|
+
and the migration-window note below); the payload
|
|
1428
|
+
`operation_type` field always remains `thumbnail`.
|
|
1429
|
+
`audio_watermark` is `availability: planned` +
|
|
1430
|
+
`required_tier: enterprise` so workflow-create rejects with
|
|
1431
|
+
422 + 403 today.
|
|
1432
|
+
- Multi-input operations (merge, archive, image_watermark,
|
|
1433
|
+
custom_luma, audio_overlay): use `sources` array. Merge
|
|
1434
|
+
additionally requires `output_type`. image_watermark,
|
|
1435
|
+
custom_luma, and audio_overlay use `role` per
|
|
1436
|
+
`JobInputV2.role`. custom_luma and audio_overlay are
|
|
1437
|
+
`availability: planned` so workflow-create rejects with 422
|
|
1438
|
+
today.
|
|
1439
|
+
|
|
1440
|
+
**Migration window note.** During the thumbnail sub-type
|
|
1441
|
+
migration, both `operation_type=thumbnail` (legacy) and
|
|
1442
|
+
`operation_type=thumbnail_{image,video,document,office}` (new)
|
|
1443
|
+
are valid routing targets. The API publisher currently emits
|
|
1444
|
+
the legacy value only; sub-type adoption is a follow-up API PR.
|
|
1445
|
+
contentType: application/json
|
|
1446
|
+
headers:
|
|
1447
|
+
$ref: '#/components/schemas/OperationRequestAttributes'
|
|
1448
|
+
payload:
|
|
1449
|
+
$ref: '#/components/schemas/OperationRequest'
|
|
1450
|
+
examples:
|
|
1451
|
+
- name: Thumbnail (legacy)
|
|
1452
|
+
summary: Generate a thumbnail for an image using the legacy thumbnail routing target
|
|
1453
|
+
headers:
|
|
1454
|
+
operation_type: "thumbnail"
|
|
1455
|
+
media_group: "image"
|
|
1456
|
+
payload:
|
|
1457
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e120"
|
|
1458
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e220"
|
|
1459
|
+
operation_type: "thumbnail"
|
|
1460
|
+
file_type: "image/jpeg"
|
|
1461
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1462
|
+
source_key: "uploads/018f9c42-iijj/photo.jpg"
|
|
1463
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1464
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e120/018f9c42-5d6b-7481-b3df-9fd0a0a5e220/"
|
|
1465
|
+
options:
|
|
1466
|
+
width: 320
|
|
1467
|
+
height: 240
|
|
1468
|
+
fit: "crop"
|
|
1469
|
+
format: "jpg"
|
|
1470
|
+
- name: Thumbnail Image (sub-type)
|
|
1471
|
+
summary: Generate a thumbnail for an image using the new thumbnail_image sub-type routing target. The SNS attribute `operation_type` carries the sub-type (drives routing); the payload `operation_type` carries the base value (`thumbnail`).
|
|
1472
|
+
headers:
|
|
1473
|
+
operation_type: "thumbnail_image"
|
|
1474
|
+
media_group: "image"
|
|
1475
|
+
payload:
|
|
1476
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e121"
|
|
1477
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e221"
|
|
1478
|
+
operation_type: "thumbnail"
|
|
1479
|
+
file_type: "image/png"
|
|
1480
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1481
|
+
source_key: "uploads/018f9c42-kkll/screenshot.png"
|
|
1482
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1483
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e121/018f9c42-5d6b-7481-b3df-9fd0a0a5e221/"
|
|
1484
|
+
options:
|
|
1485
|
+
width: 512
|
|
1486
|
+
height: 512
|
|
1487
|
+
fit: "max"
|
|
1488
|
+
format: "webp"
|
|
1489
|
+
- name: Image Watermark (file overlay)
|
|
1490
|
+
summary: Apply a PNG logo overlay to a JPEG image (V2 multi-input Path B)
|
|
1491
|
+
headers:
|
|
1492
|
+
operation_type: "image_watermark"
|
|
1493
|
+
media_group: "image"
|
|
1494
|
+
payload:
|
|
1495
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e118"
|
|
1496
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e210"
|
|
1497
|
+
operation_type: "image_watermark"
|
|
1498
|
+
file_type: "image/jpeg"
|
|
1499
|
+
sources:
|
|
1500
|
+
- role: "base"
|
|
1501
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1502
|
+
source_key: "uploads/018f9c42-eeff/photo.jpg"
|
|
1503
|
+
- role: "overlay"
|
|
1504
|
+
source_bucket: "gisl-stg-euw1-assets"
|
|
1505
|
+
source_key: "brand/logo.png"
|
|
1506
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1507
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e118/018f9c42-5d6b-7481-b3df-9fd0a0a5e210/"
|
|
1508
|
+
options:
|
|
1509
|
+
anchor: "bottom_right"
|
|
1510
|
+
margin_x: "20px"
|
|
1511
|
+
margin_y: "20px"
|
|
1512
|
+
opacity: 0.6
|
|
1513
|
+
overlay_width: "200px"
|
|
1514
|
+
- name: Text Watermark (tiled)
|
|
1515
|
+
summary: Render a rotated tiled text watermark across a PNG image (V2 single-input)
|
|
1516
|
+
headers:
|
|
1517
|
+
operation_type: "text_watermark"
|
|
1518
|
+
media_group: "image"
|
|
1519
|
+
payload:
|
|
1520
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e119"
|
|
1521
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e211"
|
|
1522
|
+
operation_type: "text_watermark"
|
|
1523
|
+
file_type: "image/png"
|
|
1524
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1525
|
+
source_key: "uploads/018f9c42-gghh/screenshot.png"
|
|
1526
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1527
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e119/018f9c42-5d6b-7481-b3df-9fd0a0a5e211/"
|
|
1528
|
+
options:
|
|
1529
|
+
text: "CONFIDENTIAL"
|
|
1530
|
+
font_size: 64
|
|
1531
|
+
color: "#FF000080"
|
|
1532
|
+
font_family: "liberation_sans"
|
|
1533
|
+
rotation: -45
|
|
1534
|
+
watermark_mode: "tiled"
|
|
1535
|
+
tile_spacing: 120
|
|
1536
|
+
opacity: 0.4
|
|
1537
|
+
- name: Image Convert
|
|
1538
|
+
summary: Convert a PNG image to WebP
|
|
1539
|
+
headers:
|
|
1540
|
+
operation_type: "convert"
|
|
1541
|
+
media_group: "image"
|
|
1542
|
+
payload:
|
|
1543
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e122"
|
|
1544
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e222"
|
|
1545
|
+
operation_type: "convert"
|
|
1546
|
+
file_type: "image/png"
|
|
1547
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1548
|
+
source_key: "uploads/018f9c42-mmnn/diagram.png"
|
|
1549
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1550
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e122/018f9c42-5d6b-7481-b3df-9fd0a0a5e222/"
|
|
1551
|
+
options:
|
|
1552
|
+
output_format: "webp"
|
|
1553
|
+
quality: 85
|
|
1554
|
+
- name: Video Merge
|
|
1555
|
+
summary: Concatenate multiple video files
|
|
1556
|
+
headers:
|
|
1557
|
+
operation_type: "merge"
|
|
1558
|
+
media_group: "video"
|
|
1559
|
+
payload:
|
|
1560
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e114"
|
|
1561
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e202"
|
|
1562
|
+
operation_type: "merge"
|
|
1563
|
+
file_type: "video/mp4"
|
|
1564
|
+
output_type: "video"
|
|
1565
|
+
sources:
|
|
1566
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1567
|
+
key: "jobs/018f9c42-aaa1/018f9c42-bbb1/intro.mp4"
|
|
1568
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1569
|
+
key: "jobs/018f9c42-aaa2/018f9c42-bbb2/content.mp4"
|
|
1570
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1571
|
+
key: "jobs/018f9c42-aaa3/018f9c42-bbb3/outro.mp4"
|
|
1572
|
+
transition: "none"
|
|
1573
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1574
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e114/018f9c42-5d6b-7481-b3df-9fd0a0a5e202/"
|
|
1575
|
+
options:
|
|
1576
|
+
transition: "crossfade"
|
|
1577
|
+
crossfade_duration: 1.0
|
|
1578
|
+
- name: Image Merge to GIF
|
|
1579
|
+
summary: Merge multiple images into an animated GIF
|
|
1580
|
+
headers:
|
|
1581
|
+
operation_type: "merge"
|
|
1582
|
+
media_group: "image"
|
|
1583
|
+
payload:
|
|
1584
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e115"
|
|
1585
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e203"
|
|
1586
|
+
operation_type: "merge"
|
|
1587
|
+
file_type: "image/png"
|
|
1588
|
+
output_type: "gif"
|
|
1589
|
+
sources:
|
|
1590
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1591
|
+
key: "jobs/018f9c42-aaa1/018f9c42-bbb1/frame1.png"
|
|
1592
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1593
|
+
key: "jobs/018f9c42-aaa2/018f9c42-bbb2/frame2.png"
|
|
1594
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1595
|
+
key: "jobs/018f9c42-aaa3/018f9c42-bbb3/frame3.png"
|
|
1596
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1597
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e115/018f9c42-5d6b-7481-b3df-9fd0a0a5e203/"
|
|
1598
|
+
options:
|
|
1599
|
+
frame_delay: 100
|
|
1600
|
+
loop: true
|
|
1601
|
+
- name: Archive
|
|
1602
|
+
summary: Bundle multiple files into a ZIP archive (no media_group attribute — archive is media-agnostic)
|
|
1603
|
+
headers:
|
|
1604
|
+
operation_type: "archive"
|
|
1605
|
+
payload:
|
|
1606
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e117"
|
|
1607
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e205"
|
|
1608
|
+
operation_type: "archive"
|
|
1609
|
+
sources:
|
|
1610
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1611
|
+
key: "jobs/018f9c42-aaa1/018f9c42-bbb1/photo_compressed.png"
|
|
1612
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1613
|
+
key: "jobs/018f9c42-aaa2/018f9c42-bbb2/video_compressed.mp4"
|
|
1614
|
+
- bucket: "gisl-stg-euw1-output"
|
|
1615
|
+
key: "jobs/018f9c42-aaa3/018f9c42-bbb3/report_compressed.pdf"
|
|
1616
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1617
|
+
output_key_prefix: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e117/018f9c42-5d6b-7481-b3df-9fd0a0a5e205/"
|
|
1618
|
+
options:
|
|
1619
|
+
format: "zip"
|
|
1620
|
+
|
|
1621
|
+
# ============================================
|
|
1622
|
+
# OPERATION PROGRESS MESSAGE
|
|
1623
|
+
# ============================================
|
|
1624
|
+
|
|
1625
|
+
OperationProgressMessage:
|
|
1626
|
+
name: OperationProgress
|
|
1627
|
+
title: Operation Progress
|
|
1628
|
+
summary: Progress update during operation processing
|
|
1629
|
+
description: |
|
|
1630
|
+
Lightweight message published by Lambda during operation processing.
|
|
1631
|
+
Used for real-time status tracking via SSE to the frontend.
|
|
1632
|
+
|
|
1633
|
+
**API Handling:**
|
|
1634
|
+
- First progress (started): Update Operation status to in_progress in DB
|
|
1635
|
+
- Subsequent progress: Update Redis cache only (not DB), forward via SSE
|
|
1636
|
+
|
|
1637
|
+
**Frontend Consumption:**
|
|
1638
|
+
- Via SSE endpoint: GET /api/workflows/{id}/events
|
|
1639
|
+
contentType: application/json
|
|
1640
|
+
headers:
|
|
1641
|
+
$ref: '#/components/schemas/FifoMessageHeaders'
|
|
1642
|
+
payload:
|
|
1643
|
+
$ref: '#/components/schemas/OperationProgress'
|
|
1644
|
+
examples:
|
|
1645
|
+
- name: Operation Started
|
|
1646
|
+
summary: Operation has been picked up by Lambda
|
|
1647
|
+
payload:
|
|
1648
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
1649
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
1650
|
+
operation_type: "compress"
|
|
1651
|
+
status: "started"
|
|
1652
|
+
progress: 0
|
|
1653
|
+
- name: Downloading
|
|
1654
|
+
summary: Lambda is downloading file from S3
|
|
1655
|
+
payload:
|
|
1656
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
1657
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
1658
|
+
operation_type: "compress"
|
|
1659
|
+
status: "downloading"
|
|
1660
|
+
progress: 10
|
|
1661
|
+
stage: "Fetching file from S3"
|
|
1662
|
+
- name: Processing
|
|
1663
|
+
summary: Lambda is actively processing the operation
|
|
1664
|
+
payload:
|
|
1665
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
1666
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
1667
|
+
operation_type: "compress"
|
|
1668
|
+
status: "processing"
|
|
1669
|
+
progress: 55
|
|
1670
|
+
stage: "Compressing image"
|
|
1671
|
+
- name: Uploading
|
|
1672
|
+
summary: Lambda is uploading result to S3
|
|
1673
|
+
payload:
|
|
1674
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
1675
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
1676
|
+
operation_type: "compress"
|
|
1677
|
+
status: "uploading"
|
|
1678
|
+
progress: 90
|
|
1679
|
+
stage: "Saving result to S3"
|
|
1680
|
+
|
|
1681
|
+
# ============================================
|
|
1682
|
+
# OPERATION RESULT MESSAGE
|
|
1683
|
+
# ============================================
|
|
1684
|
+
|
|
1685
|
+
# ============================================
|
|
1686
|
+
# UPLOAD-PROBE MESSAGES (per ticket vBlEurU7)
|
|
1687
|
+
# ============================================
|
|
1688
|
+
|
|
1689
|
+
UploadProbeRequestMessage:
|
|
1690
|
+
name: UploadProbeRequest
|
|
1691
|
+
title: Upload Probe Request
|
|
1692
|
+
summary: Request for the upload-probe Lambda to analyse an uploaded file
|
|
1693
|
+
description: |
|
|
1694
|
+
Request published by the API to the upload-probe Lambda. The
|
|
1695
|
+
same payload shape is also used as the Lambda invoke payload
|
|
1696
|
+
on the synchronous `POST /api/uploads/{id}/probe` path.
|
|
1697
|
+
|
|
1698
|
+
**Invocation paths:**
|
|
1699
|
+
- **Sync (Lambda RequestResponse)** — backs
|
|
1700
|
+
`POST /api/uploads/{id}/probe`. The API Lambda invoker
|
|
1701
|
+
serialises this payload into the Invoke event body and
|
|
1702
|
+
returns the Lambda response (`UploadProbeResponse` from
|
|
1703
|
+
`openapi/api.yaml`) inline.
|
|
1704
|
+
- **Async (SNS -> SQS)** — published to the
|
|
1705
|
+
`upload-probe-requests` topic on upload finalize for eager
|
|
1706
|
+
`rich_metadata` enrichment. The Lambda consumes from the
|
|
1707
|
+
subscribed queue and publishes a completion to the
|
|
1708
|
+
`upload-probe-completions` queue.
|
|
1709
|
+
|
|
1710
|
+
The Lambda differentiates the two paths from the AWS event
|
|
1711
|
+
source (Lambda RequestResponse vs SNS event) — no flag in
|
|
1712
|
+
the payload distinguishes them.
|
|
1713
|
+
contentType: application/json
|
|
1714
|
+
payload:
|
|
1715
|
+
$ref: '#/components/schemas/UploadProbeRequest'
|
|
1716
|
+
examples:
|
|
1717
|
+
- name: Async upload-finalize probe
|
|
1718
|
+
summary: Eager enrichment for a long-form video upload
|
|
1719
|
+
payload:
|
|
1720
|
+
file_id: "019539ab-1111-7000-8000-000000000010"
|
|
1721
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1722
|
+
source_key: "uploads/019539ab-1111-7000-8000-000000000010/clip.mp4"
|
|
1723
|
+
file_type: "video/mp4"
|
|
1724
|
+
idempotency_key: "upload-finalize:019539ab-1111-7000-8000-000000000010"
|
|
1725
|
+
requested_at: "2026-05-06T13:50:00Z"
|
|
1726
|
+
- name: Sync preflight probe
|
|
1727
|
+
summary: Caller-initiated preflight via POST /api/uploads/{id}/probe
|
|
1728
|
+
payload:
|
|
1729
|
+
file_id: "019539ab-1111-7000-8000-000000000011"
|
|
1730
|
+
source_bucket: "gisl-stg-euw1-input"
|
|
1731
|
+
source_key: "uploads/019539ab-1111-7000-8000-000000000011/clip.mp4"
|
|
1732
|
+
file_type: "video/mp4"
|
|
1733
|
+
idempotency_key: "019539ab-1111-7000-8000-000000000011"
|
|
1734
|
+
requested_at: "2026-05-06T13:50:00Z"
|
|
1735
|
+
|
|
1736
|
+
UploadProbeCompletionMessage:
|
|
1737
|
+
name: UploadProbeCompletion
|
|
1738
|
+
title: Upload Probe Completion
|
|
1739
|
+
summary: Completion notification from the upload-probe Lambda (async branch only)
|
|
1740
|
+
description: |
|
|
1741
|
+
Published by the upload-probe Lambda to the
|
|
1742
|
+
`upload-probe-completions` queue when the async branch
|
|
1743
|
+
finishes. The payload carries either a successful probe
|
|
1744
|
+
result (parity with `UploadProbeResponse` from
|
|
1745
|
+
`openapi/api.yaml`) or a failure envelope (`error_code` +
|
|
1746
|
+
`error_message`).
|
|
1747
|
+
|
|
1748
|
+
**Idempotency.** `idempotency_key` is echoed from the
|
|
1749
|
+
request so the API consumer can deduplicate against its
|
|
1750
|
+
upload row's persisted probe state.
|
|
1751
|
+
|
|
1752
|
+
Sync invocations do not publish here — sync results are
|
|
1753
|
+
returned inline as `UploadProbeResponse`.
|
|
1754
|
+
contentType: application/json
|
|
1755
|
+
payload:
|
|
1756
|
+
$ref: '#/components/schemas/UploadProbeCompletion'
|
|
1757
|
+
examples:
|
|
1758
|
+
- name: Successful probe (long-form video with audio track)
|
|
1759
|
+
summary: Lambda extracted full media metadata for a 4K H.265 video
|
|
1760
|
+
payload:
|
|
1761
|
+
file_id: "019539ab-1111-7000-8000-000000000010"
|
|
1762
|
+
idempotency_key: "upload-finalize:019539ab-1111-7000-8000-000000000010"
|
|
1763
|
+
probe_status: "ok"
|
|
1764
|
+
processing_class_pre_assignment: "long_form"
|
|
1765
|
+
media_metadata:
|
|
1766
|
+
duration_seconds: 5400
|
|
1767
|
+
width: 3840
|
|
1768
|
+
height: 2160
|
|
1769
|
+
codec: "h265"
|
|
1770
|
+
audio_codec: "aac"
|
|
1771
|
+
container: "mp4"
|
|
1772
|
+
fps: 23.976
|
|
1773
|
+
bitrate_bps: 18000000
|
|
1774
|
+
audio_layout: "stereo"
|
|
1775
|
+
channels: 2
|
|
1776
|
+
sample_rate_hz: 48000
|
|
1777
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1778
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1779
|
+
probe_version: "1.0.0"
|
|
1780
|
+
- name: Successful probe (audio-only)
|
|
1781
|
+
summary: MP3 podcast episode — codec under `codec`, no `audio_codec` field
|
|
1782
|
+
payload:
|
|
1783
|
+
file_id: "019539ab-1111-7000-8000-000000000020"
|
|
1784
|
+
idempotency_key: "upload-finalize:019539ab-1111-7000-8000-000000000020"
|
|
1785
|
+
probe_status: "ok"
|
|
1786
|
+
processing_class_pre_assignment: "short_form"
|
|
1787
|
+
media_metadata:
|
|
1788
|
+
duration_seconds: 2700
|
|
1789
|
+
codec: "mp3"
|
|
1790
|
+
container: "mp3"
|
|
1791
|
+
bitrate_bps: 192000
|
|
1792
|
+
audio_layout: "stereo"
|
|
1793
|
+
channels: 2
|
|
1794
|
+
sample_rate_hz: 44100
|
|
1795
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1796
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1797
|
+
probe_version: "1.0.0"
|
|
1798
|
+
- name: Successful probe (document)
|
|
1799
|
+
summary: PDF — `page_count` + `dpi` populated, video/audio fields omitted
|
|
1800
|
+
payload:
|
|
1801
|
+
file_id: "019539ab-1111-7000-8000-000000000021"
|
|
1802
|
+
idempotency_key: "upload-finalize:019539ab-1111-7000-8000-000000000021"
|
|
1803
|
+
probe_status: "ok"
|
|
1804
|
+
processing_class_pre_assignment: "short_form"
|
|
1805
|
+
media_metadata:
|
|
1806
|
+
container: "pdf"
|
|
1807
|
+
page_count: 42
|
|
1808
|
+
dpi: 300
|
|
1809
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1810
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1811
|
+
probe_version: "1.0.0"
|
|
1812
|
+
- name: Probe surfaced unsupported codec
|
|
1813
|
+
summary: Container readable; codec not in supported set
|
|
1814
|
+
payload:
|
|
1815
|
+
file_id: "019539ab-1111-7000-8000-000000000012"
|
|
1816
|
+
idempotency_key: "upload-finalize:019539ab-1111-7000-8000-000000000012"
|
|
1817
|
+
probe_status: "unsupported_codec"
|
|
1818
|
+
processing_class_pre_assignment: "blocked"
|
|
1819
|
+
media_metadata:
|
|
1820
|
+
duration_seconds: 600
|
|
1821
|
+
codec: "prores"
|
|
1822
|
+
container: "mov"
|
|
1823
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1824
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1825
|
+
probe_version: "1.0.0"
|
|
1826
|
+
- name: Probe failed (Lambda-side error)
|
|
1827
|
+
summary: S3 download failed; probe could not run
|
|
1828
|
+
payload:
|
|
1829
|
+
file_id: "019539ab-1111-7000-8000-000000000013"
|
|
1830
|
+
idempotency_key: "upload-finalize:019539ab-1111-7000-8000-000000000013"
|
|
1831
|
+
error_code: "s3_download_failed"
|
|
1832
|
+
error_message: "Failed to download source file from S3"
|
|
1833
|
+
probed_at: "2026-05-06T13:50:01Z"
|
|
1834
|
+
probe_version: "1.0.0"
|
|
1835
|
+
|
|
1836
|
+
OperationResultMessage:
|
|
1837
|
+
name: OperationResult
|
|
1838
|
+
title: Operation Result
|
|
1839
|
+
summary: Final result when operation completes or fails
|
|
1840
|
+
description: |
|
|
1841
|
+
Terminal message published by Lambda when operation finishes.
|
|
1842
|
+
Contains full details including output location, metrics, or error information.
|
|
1843
|
+
|
|
1844
|
+
**API Handling:**
|
|
1845
|
+
- Update Operation entity status in DB
|
|
1846
|
+
- Derive Job status from its operations (all completed -> job completed)
|
|
1847
|
+
- Derive Workflow status from its jobs
|
|
1848
|
+
- Clear Redis cache for this operation
|
|
1849
|
+
- Forward event via SSE to frontend
|
|
1850
|
+
|
|
1851
|
+
**Idempotency:**
|
|
1852
|
+
- Check if Operation already has a result before updating
|
|
1853
|
+
contentType: application/json
|
|
1854
|
+
headers:
|
|
1855
|
+
$ref: '#/components/schemas/FifoMessageHeaders'
|
|
1856
|
+
payload:
|
|
1857
|
+
$ref: '#/components/schemas/OperationResult'
|
|
1858
|
+
examples:
|
|
1859
|
+
- name: Successful Compression
|
|
1860
|
+
summary: Compress operation completed with metrics
|
|
1861
|
+
payload:
|
|
1862
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
1863
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
1864
|
+
operation_type: "compress"
|
|
1865
|
+
status: "completed"
|
|
1866
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1867
|
+
output_key: "jobs/018f9c42-5d6b/018f9c42-5d6b-e200/photo_compressed.png"
|
|
1868
|
+
output_size_bytes: 2097152
|
|
1869
|
+
metrics:
|
|
1870
|
+
original_size_bytes: 5242880
|
|
1871
|
+
output_size_bytes: 2097152
|
|
1872
|
+
compression_ratio: 0.40
|
|
1873
|
+
duration_ms: 1500
|
|
1874
|
+
- name: Successful Merge
|
|
1875
|
+
summary: Video merge completed
|
|
1876
|
+
payload:
|
|
1877
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e114"
|
|
1878
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e202"
|
|
1879
|
+
operation_type: "merge"
|
|
1880
|
+
status: "completed"
|
|
1881
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1882
|
+
output_key: "jobs/018f9c42-5d6b/018f9c42-5d6b-e202/merged.mp4"
|
|
1883
|
+
output_size_bytes: 157286400
|
|
1884
|
+
metrics:
|
|
1885
|
+
input_count: 3
|
|
1886
|
+
output_size_bytes: 157286400
|
|
1887
|
+
duration_ms: 8500
|
|
1888
|
+
- name: Failed - Invalid Format
|
|
1889
|
+
summary: Operation failed due to unsupported file format
|
|
1890
|
+
payload:
|
|
1891
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e113"
|
|
1892
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e201"
|
|
1893
|
+
operation_type: "compress"
|
|
1894
|
+
status: "failed"
|
|
1895
|
+
error_code: "invalid_format"
|
|
1896
|
+
error_message: "Unsupported file format: image/bmp"
|
|
1897
|
+
is_retryable: false
|
|
1898
|
+
last_progress: 10
|
|
1899
|
+
- name: Failed - Retryable
|
|
1900
|
+
summary: Operation failed with retryable S3 error
|
|
1901
|
+
payload:
|
|
1902
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
1903
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
1904
|
+
operation_type: "compress"
|
|
1905
|
+
status: "failed"
|
|
1906
|
+
error_code: "s3_download_failed"
|
|
1907
|
+
error_message: "Failed to download source file from S3"
|
|
1908
|
+
is_retryable: true
|
|
1909
|
+
last_progress: 0
|
|
1910
|
+
- name: Successful Multi-Output Convert (PDF to PNG, 3 pages)
|
|
1911
|
+
summary: Convert PDF->image fan-out result per ADR-0009
|
|
1912
|
+
payload:
|
|
1913
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e115"
|
|
1914
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e203"
|
|
1915
|
+
operation_type: "convert"
|
|
1916
|
+
status: "completed"
|
|
1917
|
+
output_bucket: "gisl-stg-euw1-output"
|
|
1918
|
+
total_output_size_bytes: 786432
|
|
1919
|
+
outputs:
|
|
1920
|
+
- output_key: "jobs/018f9c42-5d6b/018f9c42-5d6b-e203/page-001.png"
|
|
1921
|
+
output_size_bytes: 262144
|
|
1922
|
+
page_index: 1
|
|
1923
|
+
- output_key: "jobs/018f9c42-5d6b/018f9c42-5d6b-e203/page-002.png"
|
|
1924
|
+
output_size_bytes: 262144
|
|
1925
|
+
page_index: 2
|
|
1926
|
+
- output_key: "jobs/018f9c42-5d6b/018f9c42-5d6b-e203/page-003.png"
|
|
1927
|
+
output_size_bytes: 262144
|
|
1928
|
+
page_index: 3
|
|
1929
|
+
metrics:
|
|
1930
|
+
input_count: 1
|
|
1931
|
+
output_size_bytes: 786432
|
|
1932
|
+
duration_ms: 2300
|
|
1933
|
+
- name: Failed Multi-Output Convert (page 2 of 3 corrupted)
|
|
1934
|
+
summary: |
|
|
1935
|
+
Multi-output operation failed mid-stream per ADR-0009 §D3 (all-or-nothing
|
|
1936
|
+
failure). Lambda short-circuited on page 2; page 1 was uploaded before
|
|
1937
|
+
the failure, listed in outputs[] as informational data only — consumers
|
|
1938
|
+
MUST NOT treat them as usable on failure.
|
|
1939
|
+
payload:
|
|
1940
|
+
job_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e115"
|
|
1941
|
+
operation_id: "018f9c42-5d6b-7481-b3df-9fd0a0a5e203"
|
|
1942
|
+
operation_type: "convert"
|
|
1943
|
+
status: "failed"
|
|
1944
|
+
error_code: "processing_failed"
|
|
1945
|
+
error_message: "pdftocairo failed on page 2: invalid page tree node"
|
|
1946
|
+
is_retryable: false
|
|
1947
|
+
last_progress: 50
|
|
1948
|
+
outputs:
|
|
1949
|
+
- output_key: "jobs/018f9c42-5d6b/018f9c42-5d6b-e203/page-001.png"
|
|
1950
|
+
output_size_bytes: 262144
|
|
1951
|
+
page_index: 1
|
|
1952
|
+
|
|
1953
|
+
schemas:
|
|
1954
|
+
# ============================================
|
|
1955
|
+
# AVAILABILITY METADATA (decorative)
|
|
1956
|
+
# ============================================
|
|
1957
|
+
|
|
1958
|
+
AvailabilityValue:
|
|
1959
|
+
type: string
|
|
1960
|
+
description: |
|
|
1961
|
+
Availability level for an operation, mime_group, option, or
|
|
1962
|
+
per-enum-value entry per ADR-0001 §1.3. Mirrors the
|
|
1963
|
+
`AvailabilityValue` schema in `openapi/api.yaml` so SDK
|
|
1964
|
+
generators that consume both specs emit a single typed binding.
|
|
1965
|
+
|
|
1966
|
+
Used as the value of decorative `x-availability` extensions in
|
|
1967
|
+
this spec, and as the typed schema future tickets (I17
|
|
1968
|
+
`per_value_availability` primitive; I27 phased progress states)
|
|
1969
|
+
reference for availability metadata on event payloads.
|
|
1970
|
+
|
|
1971
|
+
Per ADR-0001 §1.4: when `availability` is absent, the implicit
|
|
1972
|
+
value is `stable` for consumers. `stable_pending_audit` is
|
|
1973
|
+
internal CI accounting only and never surfaces.
|
|
1974
|
+
|
|
1975
|
+
See `schemas/FORMAT.md` §Availability Taxonomy for full rules.
|
|
1976
|
+
enum:
|
|
1977
|
+
- stable
|
|
1978
|
+
- beta
|
|
1979
|
+
- experimental
|
|
1980
|
+
- planned
|
|
1981
|
+
- deprecated
|
|
1982
|
+
|
|
1983
|
+
PerValueAvailabilityEntry:
|
|
1984
|
+
type: object
|
|
1985
|
+
description: |
|
|
1986
|
+
Single per-enum-value availability entry. Mirrors
|
|
1987
|
+
`PerValueAvailabilityEntry` in `openapi/api.yaml` so SDK
|
|
1988
|
+
generators consuming both specs emit a single typed binding.
|
|
1989
|
+
|
|
1990
|
+
AsyncAPI consumers: this primitive is the canonical mechanism
|
|
1991
|
+
for tagging individual enum values at different availability
|
|
1992
|
+
levels — see `schemas/operations/merge.yaml` `transition`
|
|
1993
|
+
(per ticket I16-CONS) and `audio_watermark.method` /
|
|
1994
|
+
`audio_overlay.mode` for shipped consumers. The
|
|
1995
|
+
`ProgressStatus` enum (probing / decoding / encoding values
|
|
1996
|
+
landed via ticket I27) deliberately does NOT use
|
|
1997
|
+
`per_value_availability` — those phase statuses are
|
|
1998
|
+
long-form-operation conditional rather than caller-facing
|
|
1999
|
+
feature gates, and their visibility is controlled by which
|
|
2000
|
+
operations emit them rather than by per-value availability
|
|
2001
|
+
tags.
|
|
2002
|
+
|
|
2003
|
+
See `schemas/FORMAT.md` §Availability Taxonomy for full rules.
|
|
2004
|
+
required:
|
|
2005
|
+
- availability
|
|
2006
|
+
properties:
|
|
2007
|
+
availability:
|
|
2008
|
+
$ref: '#/components/schemas/AvailabilityValue'
|
|
2009
|
+
required_tier:
|
|
2010
|
+
description: Tier required to use this enum value. Optional.
|
|
2011
|
+
type: string
|
|
2012
|
+
enum:
|
|
2013
|
+
- free
|
|
2014
|
+
- pro
|
|
2015
|
+
- enterprise
|
|
2016
|
+
eta:
|
|
2017
|
+
type: string
|
|
2018
|
+
description: |
|
|
2019
|
+
ISO-8601 date or quarter (`2026-Q3`) when this value is
|
|
2020
|
+
expected to ship. Only meaningful for `availability: planned`.
|
|
2021
|
+
documentation_url:
|
|
2022
|
+
type: string
|
|
2023
|
+
format: uri
|
|
2024
|
+
sunset:
|
|
2025
|
+
type: string
|
|
2026
|
+
format: date
|
|
2027
|
+
|
|
2028
|
+
PerValueAvailability:
|
|
2029
|
+
type: object
|
|
2030
|
+
description: |
|
|
2031
|
+
Map of enum-value → `PerValueAvailabilityEntry`. Mirrors the
|
|
2032
|
+
OpenAPI version. Keys MUST be a subset of the option / status
|
|
2033
|
+
enum's `values[]` (or AsyncAPI message field's `enum`) array.
|
|
2034
|
+
additionalProperties:
|
|
2035
|
+
$ref: '#/components/schemas/PerValueAvailabilityEntry'
|
|
2036
|
+
|
|
2037
|
+
PerMimeAvailability:
|
|
2038
|
+
type: object
|
|
2039
|
+
description: |
|
|
2040
|
+
Map of MIME-type → `PerValueAvailabilityEntry`. Mirrors the
|
|
2041
|
+
OpenAPI `PerMimeAvailability` schema so SDK generators
|
|
2042
|
+
consuming both specs emit a single typed binding.
|
|
2043
|
+
|
|
2044
|
+
Keys MUST be a subset of the parent
|
|
2045
|
+
`mime_groups.<group>.mimes` array (CI-checked by
|
|
2046
|
+
`scripts/check-per-mime-availability.py`). Absent keys default
|
|
2047
|
+
to `availability: stable` per ADR-0001 §1.4. Per ticket
|
|
2048
|
+
[`YXYOo6gg`](https://trello.com/c/YXYOo6gg).
|
|
2049
|
+
additionalProperties:
|
|
2050
|
+
$ref: '#/components/schemas/PerValueAvailabilityEntry'
|
|
2051
|
+
|
|
2052
|
+
# ============================================
|
|
2053
|
+
# FIFO MESSAGE HEADERS
|
|
2054
|
+
# ============================================
|
|
2055
|
+
|
|
2056
|
+
FifoMessageHeaders:
|
|
2057
|
+
type: object
|
|
2058
|
+
description: |
|
|
2059
|
+
Required headers for FIFO SNS/SQS messaging.
|
|
2060
|
+
These ensure message ordering and deduplication.
|
|
2061
|
+
required:
|
|
2062
|
+
- MessageGroupId
|
|
2063
|
+
properties:
|
|
2064
|
+
MessageGroupId:
|
|
2065
|
+
type: string
|
|
2066
|
+
description: |
|
|
2067
|
+
Groups messages for FIFO ordering. Messages with the same
|
|
2068
|
+
MessageGroupId are processed in order. Use operation_id to ensure
|
|
2069
|
+
all messages for an operation are ordered correctly.
|
|
2070
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
2071
|
+
|
|
2072
|
+
# ============================================
|
|
2073
|
+
# SNS MESSAGE ATTRIBUTES - COMPRESSION BRANCH
|
|
2074
|
+
# ============================================
|
|
2075
|
+
|
|
2076
|
+
JobRequestAttributes:
|
|
2077
|
+
type: object
|
|
2078
|
+
description: |
|
|
2079
|
+
SNS message attributes for the compression-branch publish path
|
|
2080
|
+
(`publishJobRequest`). These are set as SNS message attributes on
|
|
2081
|
+
messages sent to the `job-requests` topic, not in the payload.
|
|
2082
|
+
|
|
2083
|
+
Only `job_type` is set on this branch. The Option A publisher in
|
|
2084
|
+
`compression_api` does **not** set `operation_type` or
|
|
2085
|
+
`media_group` as attributes on compression messages — the media
|
|
2086
|
+
group is encoded as `job_type` and no other attribute is used as
|
|
2087
|
+
a filter on this topic. `job_type` is derived from the API's
|
|
2088
|
+
`OperationMediaGroupResolver` output at publish time.
|
|
2089
|
+
|
|
2090
|
+
SNS uses `job_type` as the filter attribute on the `job-requests`
|
|
2091
|
+
topic; subscriptions route by `job_type` value to the four
|
|
2092
|
+
per-media-type compression queues.
|
|
2093
|
+
required:
|
|
2094
|
+
- job_type
|
|
2095
|
+
properties:
|
|
2096
|
+
job_type:
|
|
2097
|
+
type: string
|
|
2098
|
+
description: |
|
|
2099
|
+
Media type category used as the SNS filter attribute on the
|
|
2100
|
+
`job-requests` topic. The sole routing key for compression
|
|
2101
|
+
traffic.
|
|
2102
|
+
enum:
|
|
2103
|
+
- image
|
|
2104
|
+
- video
|
|
2105
|
+
- audio
|
|
2106
|
+
- document
|
|
2107
|
+
|
|
2108
|
+
# ============================================
|
|
2109
|
+
# SNS MESSAGE ATTRIBUTES - NON-COMPRESSION BRANCH
|
|
2110
|
+
# ============================================
|
|
2111
|
+
|
|
2112
|
+
OperationRequestAttributes:
|
|
2113
|
+
type: object
|
|
2114
|
+
description: |
|
|
2115
|
+
SNS message attributes for the non-compression-branch publish path
|
|
2116
|
+
(`publishOperationRequest`). These are set as SNS message
|
|
2117
|
+
attributes on messages sent to the `operations` topic, not in the
|
|
2118
|
+
payload.
|
|
2119
|
+
|
|
2120
|
+
SNS uses `operation_type` as the filter attribute on the
|
|
2121
|
+
`operations` topic; subscriptions route by `operation_type` value
|
|
2122
|
+
to per-operation queues. `media_group` is a second attribute the
|
|
2123
|
+
Option A publisher always sets on non-archive operations, but it
|
|
2124
|
+
is **not** used by SNS as a routing filter — it is informational
|
|
2125
|
+
metadata preserved for consumer observability and log correlation.
|
|
2126
|
+
|
|
2127
|
+
**Required-attribute contract** (encoded in the `allOf`
|
|
2128
|
+
conditionals below, matching the runtime guarantee in
|
|
2129
|
+
`compression_api`'s `AwsSnsOperationPublisherAdapter.php:63-73`):
|
|
2130
|
+
|
|
2131
|
+
- `operation_type` is always present.
|
|
2132
|
+
- `media_group` is required iff `operation_type != archive`.
|
|
2133
|
+
Archive is explicitly omitted because it is media-agnostic.
|
|
2134
|
+
- For `operation_type = text_watermark`, `media_group` must
|
|
2135
|
+
equal `image` (text_watermark is image-only).
|
|
2136
|
+
- For `operation_type = custom_luma`, `media_group` must
|
|
2137
|
+
equal `video` (custom_luma applies a luma matte to a video
|
|
2138
|
+
base; the operation is `availability: planned` per
|
|
2139
|
+
[I29](https://trello.com/c/EPUE5Vs1) so this constraint is
|
|
2140
|
+
contract-defined but not exercised today).
|
|
2141
|
+
- For `operation_type = audio_overlay`, `media_group` must
|
|
2142
|
+
equal `audio` or `video` (audio_overlay supports both —
|
|
2143
|
+
mixing into an audio track or into a video's audio track).
|
|
2144
|
+
Both mime_groups are `availability: planned` per
|
|
2145
|
+
[I19](https://trello.com/c/Xr3Z4GBF), so this constraint is
|
|
2146
|
+
contract-defined but not exercised today.
|
|
2147
|
+
- For `operation_type = audio_watermark`, `media_group` must
|
|
2148
|
+
equal `audio` or `video` (audio_watermark supports both —
|
|
2149
|
+
embedding into an audio asset or into a video's audio
|
|
2150
|
+
track). Both mime_groups are `availability: planned` +
|
|
2151
|
+
`required_tier: enterprise` per
|
|
2152
|
+
[I20](https://trello.com/c/omiCq7Vn), so this constraint is
|
|
2153
|
+
contract-defined but not exercised today.
|
|
2154
|
+
- For `operation_type = image_watermark`, `media_group` must
|
|
2155
|
+
equal `image` while only the stable `image` mime_group is
|
|
2156
|
+
dispatchable. The schema declares `image_gif` and `video`
|
|
2157
|
+
mime_groups at `availability: planned` (I5 — Trello AKZiOXnd);
|
|
2158
|
+
when those flip to `stable`, this constraint widens to
|
|
2159
|
+
`{image, video}` (animated GIF carries `media_group=image`).
|
|
2160
|
+
Until then the API rejects non-image bases at workflow-create
|
|
2161
|
+
time with `feature_not_available` (422), so SNS-attribute
|
|
2162
|
+
values stay constrained to `image`.
|
|
2163
|
+
- For the four thumbnail sub-types, `media_group` is constrained
|
|
2164
|
+
to the matching media:
|
|
2165
|
+
- `thumbnail_image` -> `image`
|
|
2166
|
+
- `thumbnail_video` -> `video`
|
|
2167
|
+
- `thumbnail_document` -> `document`
|
|
2168
|
+
- `thumbnail_office` -> `document` (office files are routed as
|
|
2169
|
+
documents at the media_group level)
|
|
2170
|
+
required:
|
|
2171
|
+
- operation_type
|
|
2172
|
+
properties:
|
|
2173
|
+
operation_type:
|
|
2174
|
+
type: string
|
|
2175
|
+
description: |
|
|
2176
|
+
Operation type used as the SNS filter attribute on the
|
|
2177
|
+
`operations` topic. The sole routing key for non-compression
|
|
2178
|
+
traffic.
|
|
2179
|
+
enum:
|
|
2180
|
+
- thumbnail
|
|
2181
|
+
- thumbnail_image
|
|
2182
|
+
- thumbnail_video
|
|
2183
|
+
- thumbnail_document
|
|
2184
|
+
- thumbnail_office
|
|
2185
|
+
- image_watermark
|
|
2186
|
+
- text_watermark
|
|
2187
|
+
- merge
|
|
2188
|
+
- archive
|
|
2189
|
+
- convert
|
|
2190
|
+
- custom_luma
|
|
2191
|
+
- audio_overlay
|
|
2192
|
+
- audio_watermark
|
|
2193
|
+
media_group:
|
|
2194
|
+
type: string
|
|
2195
|
+
description: |
|
|
2196
|
+
Media category. **Informational metadata, not an SNS filter
|
|
2197
|
+
attribute.** Set by the Option A publisher on every
|
|
2198
|
+
non-compress, non-archive operation for consumer observability
|
|
2199
|
+
and log correlation. Omitted for archive (media-agnostic).
|
|
2200
|
+
|
|
2201
|
+
For single-input operations, derived from `file_type` MIME
|
|
2202
|
+
prefix. For merge, derived from `output_type`.
|
|
2203
|
+
enum:
|
|
2204
|
+
- image
|
|
2205
|
+
- video
|
|
2206
|
+
- audio
|
|
2207
|
+
- document
|
|
2208
|
+
allOf:
|
|
2209
|
+
- if:
|
|
2210
|
+
properties:
|
|
2211
|
+
operation_type:
|
|
2212
|
+
not:
|
|
2213
|
+
const: archive
|
|
2214
|
+
then:
|
|
2215
|
+
required:
|
|
2216
|
+
- media_group
|
|
2217
|
+
- if:
|
|
2218
|
+
properties:
|
|
2219
|
+
operation_type:
|
|
2220
|
+
const: image_watermark
|
|
2221
|
+
then:
|
|
2222
|
+
properties:
|
|
2223
|
+
media_group:
|
|
2224
|
+
const: image
|
|
2225
|
+
- if:
|
|
2226
|
+
properties:
|
|
2227
|
+
operation_type:
|
|
2228
|
+
const: text_watermark
|
|
2229
|
+
then:
|
|
2230
|
+
properties:
|
|
2231
|
+
media_group:
|
|
2232
|
+
const: image
|
|
2233
|
+
- if:
|
|
2234
|
+
properties:
|
|
2235
|
+
operation_type:
|
|
2236
|
+
const: custom_luma
|
|
2237
|
+
then:
|
|
2238
|
+
properties:
|
|
2239
|
+
media_group:
|
|
2240
|
+
const: video
|
|
2241
|
+
- if:
|
|
2242
|
+
properties:
|
|
2243
|
+
operation_type:
|
|
2244
|
+
const: audio_overlay
|
|
2245
|
+
then:
|
|
2246
|
+
properties:
|
|
2247
|
+
media_group:
|
|
2248
|
+
enum: [audio, video]
|
|
2249
|
+
- if:
|
|
2250
|
+
properties:
|
|
2251
|
+
operation_type:
|
|
2252
|
+
const: audio_watermark
|
|
2253
|
+
then:
|
|
2254
|
+
properties:
|
|
2255
|
+
media_group:
|
|
2256
|
+
enum: [audio, video]
|
|
2257
|
+
- if:
|
|
2258
|
+
properties:
|
|
2259
|
+
operation_type:
|
|
2260
|
+
const: thumbnail_image
|
|
2261
|
+
then:
|
|
2262
|
+
properties:
|
|
2263
|
+
media_group:
|
|
2264
|
+
const: image
|
|
2265
|
+
- if:
|
|
2266
|
+
properties:
|
|
2267
|
+
operation_type:
|
|
2268
|
+
const: thumbnail_video
|
|
2269
|
+
then:
|
|
2270
|
+
properties:
|
|
2271
|
+
media_group:
|
|
2272
|
+
const: video
|
|
2273
|
+
- if:
|
|
2274
|
+
properties:
|
|
2275
|
+
operation_type:
|
|
2276
|
+
const: thumbnail_document
|
|
2277
|
+
then:
|
|
2278
|
+
properties:
|
|
2279
|
+
media_group:
|
|
2280
|
+
const: document
|
|
2281
|
+
- if:
|
|
2282
|
+
properties:
|
|
2283
|
+
operation_type:
|
|
2284
|
+
const: thumbnail_office
|
|
2285
|
+
then:
|
|
2286
|
+
properties:
|
|
2287
|
+
media_group:
|
|
2288
|
+
const: document
|
|
2289
|
+
|
|
2290
|
+
# ============================================
|
|
2291
|
+
# OPERATION REQUEST PAYLOAD SCHEMA (shared by both messages)
|
|
2292
|
+
# ============================================
|
|
2293
|
+
|
|
2294
|
+
OperationRequest:
|
|
2295
|
+
type: object
|
|
2296
|
+
description: |
|
|
2297
|
+
Message format for operation request payloads. Shared between
|
|
2298
|
+
`JobRequestMessage` (compression branch) and
|
|
2299
|
+
`OperationRequestMessage` (non-compression branch). Published by
|
|
2300
|
+
API to SNS, consumed by Lambda from SQS.
|
|
2301
|
+
|
|
2302
|
+
**Single-input operations** (compress, thumbnail, text_watermark,
|
|
2303
|
+
convert): use `source_bucket` + `source_key` for the input file.
|
|
2304
|
+
`file_type` is required.
|
|
2305
|
+
|
|
2306
|
+
**Multi-input operations** (merge, archive, image_watermark,
|
|
2307
|
+
custom_luma, audio_overlay): use `sources` array. Each entry
|
|
2308
|
+
has `bucket` + `key`. Merge entries may include per-input
|
|
2309
|
+
overrides (e.g. transition type). Merge also requires
|
|
2310
|
+
`output_type`. custom_luma and audio_overlay are
|
|
2311
|
+
`availability: planned` so workflow-create rejects with 422
|
|
2312
|
+
today; the wire shape is contract-defined.
|
|
2313
|
+
|
|
2314
|
+
Note: `media_group` is **not** a field in this payload. It exists
|
|
2315
|
+
only as an SNS MessageAttribute on the non-compression branch; on
|
|
2316
|
+
the compression branch, the routing equivalent is the `job_type`
|
|
2317
|
+
MessageAttribute, also not in the payload.
|
|
2318
|
+
required:
|
|
2319
|
+
- job_id
|
|
2320
|
+
- operation_id
|
|
2321
|
+
- operation_type
|
|
2322
|
+
- output_bucket
|
|
2323
|
+
- output_key_prefix
|
|
2324
|
+
allOf:
|
|
2325
|
+
- if:
|
|
2326
|
+
properties:
|
|
2327
|
+
operation_type:
|
|
2328
|
+
enum:
|
|
2329
|
+
- compress
|
|
2330
|
+
- thumbnail
|
|
2331
|
+
- text_watermark
|
|
2332
|
+
- convert
|
|
2333
|
+
- audio_watermark
|
|
2334
|
+
then:
|
|
2335
|
+
required:
|
|
2336
|
+
- file_type
|
|
2337
|
+
- source_bucket
|
|
2338
|
+
- source_key
|
|
2339
|
+
- if:
|
|
2340
|
+
properties:
|
|
2341
|
+
operation_type:
|
|
2342
|
+
enum: [merge, archive, image_watermark, custom_luma, audio_overlay]
|
|
2343
|
+
then:
|
|
2344
|
+
required:
|
|
2345
|
+
- sources
|
|
2346
|
+
- if:
|
|
2347
|
+
properties:
|
|
2348
|
+
operation_type:
|
|
2349
|
+
const: merge
|
|
2350
|
+
then:
|
|
2351
|
+
required:
|
|
2352
|
+
- output_type
|
|
2353
|
+
properties:
|
|
2354
|
+
job_id:
|
|
2355
|
+
type: string
|
|
2356
|
+
format: uuid
|
|
2357
|
+
description: Parent job identifier (UUID v7)
|
|
2358
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
2359
|
+
operation_id:
|
|
2360
|
+
type: string
|
|
2361
|
+
format: uuid
|
|
2362
|
+
description: Unique operation identifier (UUID v7)
|
|
2363
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
2364
|
+
operation_type:
|
|
2365
|
+
$ref: '#/components/schemas/OperationType'
|
|
2366
|
+
workflow_id:
|
|
2367
|
+
type: string
|
|
2368
|
+
format: uuid
|
|
2369
|
+
description: Parent workflow identifier (UUID v7). Present when operation belongs to a workflow.
|
|
2370
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e100"
|
|
2371
|
+
file_type:
|
|
2372
|
+
type: string
|
|
2373
|
+
description: |
|
|
2374
|
+
MIME type of the input file. Required for single-input operations.
|
|
2375
|
+
For multi-input operations, represents the primary/expected input type.
|
|
2376
|
+
|
|
2377
|
+
Examples by media group:
|
|
2378
|
+
- image: image/png, image/jpeg, image/webp, image/avif, image/gif, image/svg+xml, image/tiff
|
|
2379
|
+
- video: video/mp4, video/webm
|
|
2380
|
+
- audio: audio/mpeg, audio/ogg, audio/wav, audio/flac, audio/aac
|
|
2381
|
+
- document:
|
|
2382
|
+
- application/pdf
|
|
2383
|
+
- application/vnd.openxmlformats-officedocument.wordprocessingml.document (DOCX)
|
|
2384
|
+
- application/vnd.openxmlformats-officedocument.spreadsheetml.sheet (XLSX)
|
|
2385
|
+
- application/vnd.openxmlformats-officedocument.presentationml.presentation (PPTX)
|
|
2386
|
+
- application/vnd.oasis.opendocument.text (ODT)
|
|
2387
|
+
- application/vnd.oasis.opendocument.spreadsheet (ODS)
|
|
2388
|
+
- application/vnd.oasis.opendocument.presentation (ODP)
|
|
2389
|
+
- application/epub+zip (EPUB)
|
|
2390
|
+
example: "image/png"
|
|
2391
|
+
|
|
2392
|
+
# Single-input fields
|
|
2393
|
+
source_bucket:
|
|
2394
|
+
type: string
|
|
2395
|
+
description: S3 bucket containing the source file (single-input operations)
|
|
2396
|
+
example: "gisl-stg-euw1-input"
|
|
2397
|
+
source_key:
|
|
2398
|
+
type: string
|
|
2399
|
+
description: S3 key of the source file (single-input operations)
|
|
2400
|
+
example: "uploads/018f9c42-aabb/photo.png"
|
|
2401
|
+
|
|
2402
|
+
# Multi-input fields
|
|
2403
|
+
sources:
|
|
2404
|
+
type: array
|
|
2405
|
+
description: |
|
|
2406
|
+
Input files for multi-input operations (merge, archive,
|
|
2407
|
+
image_watermark, custom_luma, audio_overlay). Each entry
|
|
2408
|
+
specifies an S3 location. Order matters for merge
|
|
2409
|
+
(concatenation order). Per-input overrides (e.g.
|
|
2410
|
+
transition) can be inlined on each entry.
|
|
2411
|
+
Role-based multi-input operations (image_watermark,
|
|
2412
|
+
custom_luma, audio_overlay) require a `role` discriminator
|
|
2413
|
+
on each entry — see `SourceEntry.role`.
|
|
2414
|
+
items:
|
|
2415
|
+
$ref: '#/components/schemas/SourceEntry'
|
|
2416
|
+
minItems: 2
|
|
2417
|
+
|
|
2418
|
+
# Output
|
|
2419
|
+
output_bucket:
|
|
2420
|
+
type: string
|
|
2421
|
+
description: S3 bucket for the operation output
|
|
2422
|
+
example: "gisl-stg-euw1-output"
|
|
2423
|
+
output_key_prefix:
|
|
2424
|
+
type: string
|
|
2425
|
+
description: |
|
|
2426
|
+
S3 key prefix for operation output. Lambda writes output files under this prefix.
|
|
2427
|
+
Convention: jobs/{job_id}/{operation_id}/
|
|
2428
|
+
example: "jobs/018f9c42-5d6b-7481-b3df-9fd0a0a5e112/018f9c42-5d6b-7481-b3df-9fd0a0a5e200/"
|
|
2429
|
+
|
|
2430
|
+
# Merge-specific
|
|
2431
|
+
output_type:
|
|
2432
|
+
$ref: '#/components/schemas/MergeOutputType'
|
|
2433
|
+
|
|
2434
|
+
# Operation options
|
|
2435
|
+
options:
|
|
2436
|
+
type: object
|
|
2437
|
+
description: |
|
|
2438
|
+
Operation-specific options. Schema varies by operation_type and media_group.
|
|
2439
|
+
Validated by the API before publishing. Lambda trusts these are valid.
|
|
2440
|
+
See the OpenAPI spec for per-operation-type option schemas.
|
|
2441
|
+
additionalProperties: true
|
|
2442
|
+
|
|
2443
|
+
# V2 placeholders
|
|
2444
|
+
source_credentials:
|
|
2445
|
+
type: object
|
|
2446
|
+
description: |
|
|
2447
|
+
Credentials for accessing source files in external storage (V2).
|
|
2448
|
+
Not used in V1 — all sources are in GISL-managed S3 buckets.
|
|
2449
|
+
additionalProperties: true
|
|
2450
|
+
export:
|
|
2451
|
+
type: object
|
|
2452
|
+
description: |
|
|
2453
|
+
Export configuration for writing output to external storage (V2).
|
|
2454
|
+
Not used in V1 — all outputs go to GISL-managed S3 buckets.
|
|
2455
|
+
additionalProperties: true
|
|
2456
|
+
|
|
2457
|
+
SourceEntry:
|
|
2458
|
+
type: object
|
|
2459
|
+
description: |
|
|
2460
|
+
A single source file for multi-input operations (merge,
|
|
2461
|
+
archive, image_watermark, custom_luma, audio_overlay).
|
|
2462
|
+
Provides the S3 location, optional per-input overrides, and
|
|
2463
|
+
the `role` discriminator for role-based multi-input
|
|
2464
|
+
operations.
|
|
2465
|
+
required:
|
|
2466
|
+
- bucket
|
|
2467
|
+
- key
|
|
2468
|
+
properties:
|
|
2469
|
+
bucket:
|
|
2470
|
+
type: string
|
|
2471
|
+
description: S3 bucket containing the source file
|
|
2472
|
+
example: "gisl-stg-euw1-output"
|
|
2473
|
+
key:
|
|
2474
|
+
type: string
|
|
2475
|
+
description: S3 key of the source file
|
|
2476
|
+
example: "jobs/018f9c42-aaa1/018f9c42-bbb1/intro.mp4"
|
|
2477
|
+
role:
|
|
2478
|
+
# Named schema preserves the per-operation role rules in its
|
|
2479
|
+
# description; lifted from inline per ticket QokFw8VR.
|
|
2480
|
+
$ref: '#/components/schemas/JobInputRole'
|
|
2481
|
+
transition:
|
|
2482
|
+
type: string
|
|
2483
|
+
description: |
|
|
2484
|
+
Per-input transition override for video merge.
|
|
2485
|
+
Overrides the global transition option for the join point before this input.
|
|
2486
|
+
example: "none"
|
|
2487
|
+
|
|
2488
|
+
# ============================================
|
|
2489
|
+
# OPERATION PROGRESS SCHEMA
|
|
2490
|
+
# ============================================
|
|
2491
|
+
|
|
2492
|
+
OperationProgress:
|
|
2493
|
+
type: object
|
|
2494
|
+
description: |
|
|
2495
|
+
Lightweight progress update message.
|
|
2496
|
+
Published frequently during operation processing.
|
|
2497
|
+
Stored in Redis, not database (except first "started" status).
|
|
2498
|
+
|
|
2499
|
+
**Important**: Progress reaches 100 only on successful completion.
|
|
2500
|
+
On failure, progress stops at the last known value.
|
|
2501
|
+
required:
|
|
2502
|
+
- job_id
|
|
2503
|
+
- operation_id
|
|
2504
|
+
- operation_type
|
|
2505
|
+
- status
|
|
2506
|
+
- progress
|
|
2507
|
+
properties:
|
|
2508
|
+
job_id:
|
|
2509
|
+
type: string
|
|
2510
|
+
format: uuid
|
|
2511
|
+
description: Parent job identifier for correlation
|
|
2512
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
2513
|
+
operation_id:
|
|
2514
|
+
type: string
|
|
2515
|
+
format: uuid
|
|
2516
|
+
description: Operation identifier matching the original request
|
|
2517
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
2518
|
+
operation_type:
|
|
2519
|
+
$ref: '#/components/schemas/OperationType'
|
|
2520
|
+
status:
|
|
2521
|
+
$ref: '#/components/schemas/ProgressStatus'
|
|
2522
|
+
progress:
|
|
2523
|
+
type: integer
|
|
2524
|
+
minimum: 0
|
|
2525
|
+
maximum: 100
|
|
2526
|
+
description: Progress percentage (0-100)
|
|
2527
|
+
example: 55
|
|
2528
|
+
stage:
|
|
2529
|
+
type: string
|
|
2530
|
+
description: Human-readable description of current processing stage
|
|
2531
|
+
example: "Compressing image"
|
|
2532
|
+
phase_input_index:
|
|
2533
|
+
type: integer
|
|
2534
|
+
minimum: 1
|
|
2535
|
+
description: |
|
|
2536
|
+
1-based index of the input currently being processed in
|
|
2537
|
+
this phase. Emitted only when `status` is `probing` or
|
|
2538
|
+
`decoding` (and optionally `encoding` for multi-output
|
|
2539
|
+
operations) to give callers visibility into long-form
|
|
2540
|
+
jobs that internally process inputs sequentially.
|
|
2541
|
+
Frontend renders "probing input 2/4" / "decoding input
|
|
2542
|
+
3/4" without callers having to decompose into multiple
|
|
2543
|
+
jobs. Per ticket I27 (Trello 1R3K3bsG) + plan v5 §F8.3.
|
|
2544
|
+
example: 2
|
|
2545
|
+
phase_total_inputs:
|
|
2546
|
+
type: integer
|
|
2547
|
+
minimum: 1
|
|
2548
|
+
description: |
|
|
2549
|
+
Total number of inputs expected in this phase. Pairs with
|
|
2550
|
+
`phase_input_index`. For single-input operations (most
|
|
2551
|
+
ops) `phase_total_inputs: 1` and `phase_input_index: 1`
|
|
2552
|
+
during the relevant phase. For multi-input merge,
|
|
2553
|
+
archive, image_watermark, custom_luma, and audio_overlay,
|
|
2554
|
+
this matches the inputs[] count. Per ticket I27.
|
|
2555
|
+
example: 4
|
|
2556
|
+
|
|
2557
|
+
# ============================================
|
|
2558
|
+
# OPERATION RESULT SCHEMA
|
|
2559
|
+
# ============================================
|
|
2560
|
+
|
|
2561
|
+
OperationResult:
|
|
2562
|
+
type: object
|
|
2563
|
+
description: |
|
|
2564
|
+
Terminal message with full operation results.
|
|
2565
|
+
Stored in database as part of the Operation entity.
|
|
2566
|
+
|
|
2567
|
+
**Important**: This message MUST always be sent, whether the operation
|
|
2568
|
+
succeeds or fails. It is the definitive signal that processing is complete.
|
|
2569
|
+
|
|
2570
|
+
## Single-output vs multi-output completion
|
|
2571
|
+
|
|
2572
|
+
Per [ADR-0009](../docs/decisions/0009-multi-output-result-envelope.md),
|
|
2573
|
+
successful completion uses one of two mutually-exclusive shapes:
|
|
2574
|
+
|
|
2575
|
+
- **Single-output** (compress, watermark, merge, archive, convert
|
|
2576
|
+
single-output, thumbnail): top-level `output_key` + `output_size_bytes`
|
|
2577
|
+
are present; `outputs[]` is absent.
|
|
2578
|
+
- **Multi-output** (convert PDF->image; future fan-out operations):
|
|
2579
|
+
`outputs[]` + `total_output_size_bytes` are present; top-level
|
|
2580
|
+
`output_key` / `output_size_bytes` are absent. Consumers MUST use
|
|
2581
|
+
`outputs.length` (or its language equivalent) for the count; per
|
|
2582
|
+
ADR-0009 §D4 a denormalised `output_count` field was deliberately
|
|
2583
|
+
rejected.
|
|
2584
|
+
|
|
2585
|
+
`output_bucket` is shared across both shapes — all outputs in a
|
|
2586
|
+
multi-output operation live in the same bucket.
|
|
2587
|
+
|
|
2588
|
+
Failure (`status: failed`) is unified across both shapes: one
|
|
2589
|
+
`error_code` + `error_message` + `is_retryable` at the top level; no
|
|
2590
|
+
per-output error array (all-or-nothing failure per ADR-0009 §D3).
|
|
2591
|
+
`outputs[]` MAY be present on failure as informational data showing
|
|
2592
|
+
which outputs completed before the failing one; consumers MUST NOT
|
|
2593
|
+
treat them as usable.
|
|
2594
|
+
required:
|
|
2595
|
+
- job_id
|
|
2596
|
+
- operation_id
|
|
2597
|
+
- operation_type
|
|
2598
|
+
- status
|
|
2599
|
+
oneOf:
|
|
2600
|
+
- title: SingleOutputCompletion
|
|
2601
|
+
description: |
|
|
2602
|
+
Legacy single-output completion. Used by compress, watermark,
|
|
2603
|
+
merge, archive, convert single-output, and thumbnail operations.
|
|
2604
|
+
properties:
|
|
2605
|
+
status:
|
|
2606
|
+
const: completed
|
|
2607
|
+
required:
|
|
2608
|
+
- output_bucket
|
|
2609
|
+
- output_key
|
|
2610
|
+
- output_size_bytes
|
|
2611
|
+
not:
|
|
2612
|
+
anyOf:
|
|
2613
|
+
- required: [outputs]
|
|
2614
|
+
- required: [output_count]
|
|
2615
|
+
- required: [total_output_size_bytes]
|
|
2616
|
+
- title: MultiOutputCompletion
|
|
2617
|
+
description: |
|
|
2618
|
+
Multi-output completion. Used by convert PDF->image and future
|
|
2619
|
+
fan-out operations. Per ADR-0009.
|
|
2620
|
+
properties:
|
|
2621
|
+
status:
|
|
2622
|
+
const: completed
|
|
2623
|
+
required:
|
|
2624
|
+
- output_bucket
|
|
2625
|
+
- outputs
|
|
2626
|
+
- total_output_size_bytes
|
|
2627
|
+
not:
|
|
2628
|
+
anyOf:
|
|
2629
|
+
- required: [output_key]
|
|
2630
|
+
- required: [output_size_bytes]
|
|
2631
|
+
- title: Failure
|
|
2632
|
+
description: |
|
|
2633
|
+
Operation failed (single- or multi-output). One top-level error
|
|
2634
|
+
envelope per ADR-0009 §D3 (all-or-nothing failure). `outputs[]`
|
|
2635
|
+
MAY be present with partial results as informational data; do
|
|
2636
|
+
not consume.
|
|
2637
|
+
properties:
|
|
2638
|
+
status:
|
|
2639
|
+
const: failed
|
|
2640
|
+
required:
|
|
2641
|
+
- error_code
|
|
2642
|
+
- error_message
|
|
2643
|
+
- is_retryable
|
|
2644
|
+
properties:
|
|
2645
|
+
job_id:
|
|
2646
|
+
type: string
|
|
2647
|
+
format: uuid
|
|
2648
|
+
description: Parent job identifier for correlation
|
|
2649
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e112"
|
|
2650
|
+
operation_id:
|
|
2651
|
+
type: string
|
|
2652
|
+
format: uuid
|
|
2653
|
+
description: Operation identifier matching the original request
|
|
2654
|
+
example: "018f9c42-5d6b-7481-b3df-9fd0a0a5e200"
|
|
2655
|
+
operation_type:
|
|
2656
|
+
$ref: '#/components/schemas/OperationType'
|
|
2657
|
+
status:
|
|
2658
|
+
$ref: '#/components/schemas/ResultStatus'
|
|
2659
|
+
|
|
2660
|
+
# Shared success field (both single- and multi-output)
|
|
2661
|
+
output_bucket:
|
|
2662
|
+
type: string
|
|
2663
|
+
description: |
|
|
2664
|
+
S3 bucket where output file(s) are stored. Present on completion
|
|
2665
|
+
for both single- and multi-output operations; all outputs in a
|
|
2666
|
+
multi-output operation share this bucket. Absent on failure.
|
|
2667
|
+
example: "gisl-stg-euw1-output"
|
|
2668
|
+
|
|
2669
|
+
# Single-output success fields (legacy; per ADR-0009 SingleOutputCompletion)
|
|
2670
|
+
output_key:
|
|
2671
|
+
type: string
|
|
2672
|
+
description: |
|
|
2673
|
+
S3 key of the output file. Single-output completion only — mutually
|
|
2674
|
+
exclusive with `outputs[]`. Absent for multi-output operations and
|
|
2675
|
+
on failure.
|
|
2676
|
+
example: "jobs/018f9c42-5d6b/018f9c42-5d6b-e200/photo_compressed.png"
|
|
2677
|
+
output_size_bytes:
|
|
2678
|
+
type: integer
|
|
2679
|
+
format: int64
|
|
2680
|
+
description: |
|
|
2681
|
+
Output file size in bytes. Single-output completion only — mutually
|
|
2682
|
+
exclusive with `outputs[]`. Absent for multi-output operations and
|
|
2683
|
+
on failure.
|
|
2684
|
+
example: 2097152
|
|
2685
|
+
|
|
2686
|
+
# Multi-output success fields (per ADR-0009 MultiOutputCompletion)
|
|
2687
|
+
outputs:
|
|
2688
|
+
type: array
|
|
2689
|
+
minItems: 1
|
|
2690
|
+
maxItems: 200
|
|
2691
|
+
description: |
|
|
2692
|
+
Per-output details for multi-output operations (e.g. convert
|
|
2693
|
+
PDF->image emits one entry per page). Mutually exclusive with
|
|
2694
|
+
top-level `output_key` / `output_size_bytes` on completion. MAY
|
|
2695
|
+
be present on failure as informational data showing partial
|
|
2696
|
+
results; consumers MUST NOT treat those as usable. See ADR-0009.
|
|
2697
|
+
|
|
2698
|
+
**`maxItems: 200`** is a worst-case transport-layer defence
|
|
2699
|
+
against SQS/SNS's 256 KiB payload cap. Worst-case per-entry size
|
|
2700
|
+
is ~1080 bytes (1024-char `output_key` at the S3 hard limit + ~55
|
|
2701
|
+
bytes JSON envelope per entry); 200 entries × 1080 bytes ≈ 216
|
|
2702
|
+
KB, leaving ~40 KB headroom for the outer message envelope
|
|
2703
|
+
(`job_id`, `operation_id`, `metrics`, `total_output_size_bytes`,
|
|
2704
|
+
etc.). Typical Lambda-generated keys are ~110 chars so the
|
|
2705
|
+
realistic per-message size stays well under the cap; this bound
|
|
2706
|
+
defends against the worst case, not the typical case.
|
|
2707
|
+
|
|
2708
|
+
Operations that could theoretically exceed 200 outputs from one
|
|
2709
|
+
logical operation (e.g. convert PDF->image on a >200-page PDF)
|
|
2710
|
+
MUST enforce a corresponding upper bound on the input side
|
|
2711
|
+
(per-operation page-range / count option in the operation's
|
|
2712
|
+
`schemas/operations/*.yaml`); the transport bound is defence in
|
|
2713
|
+
depth, not the primary user-facing limit. See ADR-0009 §D5.
|
|
2714
|
+
items:
|
|
2715
|
+
$ref: '#/components/schemas/OperationResultOutputEntry'
|
|
2716
|
+
total_output_size_bytes:
|
|
2717
|
+
type: integer
|
|
2718
|
+
format: int64
|
|
2719
|
+
minimum: 0
|
|
2720
|
+
description: |
|
|
2721
|
+
Aggregate size of all `outputs[]` in bytes. Equals
|
|
2722
|
+
`sum(outputs[].output_size_bytes)`. Emitted only with multi-output
|
|
2723
|
+
completion. Used for billing and aggregate observability. Per
|
|
2724
|
+
ADR-0009 §D4, this is denormalised against the per-entry sum;
|
|
2725
|
+
consumers SHOULD trust the per-entry sum if the two disagree (and
|
|
2726
|
+
log a warning).
|
|
2727
|
+
example: 786432
|
|
2728
|
+
|
|
2729
|
+
metrics:
|
|
2730
|
+
$ref: '#/components/schemas/OperationMetrics'
|
|
2731
|
+
|
|
2732
|
+
# Failure fields
|
|
2733
|
+
error_code:
|
|
2734
|
+
$ref: '#/components/schemas/ErrorCode'
|
|
2735
|
+
error_message:
|
|
2736
|
+
type: string
|
|
2737
|
+
description: Human-readable error message (failed only)
|
|
2738
|
+
example: "Unsupported file format: image/bmp"
|
|
2739
|
+
is_retryable:
|
|
2740
|
+
type: boolean
|
|
2741
|
+
description: Whether the operation could be retried (failed only)
|
|
2742
|
+
default: false
|
|
2743
|
+
last_progress:
|
|
2744
|
+
type: integer
|
|
2745
|
+
minimum: 0
|
|
2746
|
+
maximum: 100
|
|
2747
|
+
description: Progress percentage when the operation failed (failed only)
|
|
2748
|
+
example: 10
|
|
2749
|
+
|
|
2750
|
+
OperationResultOutputEntry:
|
|
2751
|
+
type: object
|
|
2752
|
+
description: |
|
|
2753
|
+
Single entry in the `OperationResult.outputs[]` array for multi-output
|
|
2754
|
+
operations. Per ADR-0009.
|
|
2755
|
+
|
|
2756
|
+
Each entry represents one output file produced by the operation, with
|
|
2757
|
+
its S3 key, size, and an indexing field (`page_index` for PDF-page
|
|
2758
|
+
outputs, `position` for generic ordinals). Per ADR-0009 §D2, an
|
|
2759
|
+
operation uses **one** indexing field consistently for all its
|
|
2760
|
+
outputs; the two are mutually exclusive within an entry.
|
|
2761
|
+
required:
|
|
2762
|
+
- output_key
|
|
2763
|
+
- output_size_bytes
|
|
2764
|
+
oneOf:
|
|
2765
|
+
- title: PageIndexed
|
|
2766
|
+
description: PDF-page output (convert PDF->image).
|
|
2767
|
+
required: [page_index]
|
|
2768
|
+
not: { required: [position] }
|
|
2769
|
+
- title: PositionIndexed
|
|
2770
|
+
description: Generic ordinal output (frame strip, chapter split).
|
|
2771
|
+
required: [position]
|
|
2772
|
+
not: { required: [page_index] }
|
|
2773
|
+
- title: Unindexed
|
|
2774
|
+
description: |
|
|
2775
|
+
Output without an explicit indexing field. Reserved for future
|
|
2776
|
+
operations that index by something other than page/position.
|
|
2777
|
+
Schema-valid but not currently emitted by any operation.
|
|
2778
|
+
not:
|
|
2779
|
+
anyOf:
|
|
2780
|
+
- required: [page_index]
|
|
2781
|
+
- required: [position]
|
|
2782
|
+
properties:
|
|
2783
|
+
output_key:
|
|
2784
|
+
type: string
|
|
2785
|
+
maxLength: 1024
|
|
2786
|
+
description: |
|
|
2787
|
+
S3 key of this individual output file. `maxLength: 1024` matches
|
|
2788
|
+
the S3 object key hard limit; keys longer than this are rejected
|
|
2789
|
+
by S3 itself, so this is a contract-level mirror of the upstream
|
|
2790
|
+
constraint.
|
|
2791
|
+
example: "jobs/018f9c42-5d6b/018f9c42-5d6b-e200/page-001.png"
|
|
2792
|
+
output_size_bytes:
|
|
2793
|
+
type: integer
|
|
2794
|
+
format: int64
|
|
2795
|
+
minimum: 0
|
|
2796
|
+
description: Size of this individual output file in bytes.
|
|
2797
|
+
example: 262144
|
|
2798
|
+
page_index:
|
|
2799
|
+
type: integer
|
|
2800
|
+
minimum: 1
|
|
2801
|
+
description: |
|
|
2802
|
+
1-based page number for PDF-page outputs. Gapless within an
|
|
2803
|
+
operation (an N-page conversion emits `page_index` 1..N). Mutually
|
|
2804
|
+
exclusive with `position`. Per ADR-0009 §D2.
|
|
2805
|
+
example: 1
|
|
2806
|
+
position:
|
|
2807
|
+
type: integer
|
|
2808
|
+
minimum: 0
|
|
2809
|
+
description: |
|
|
2810
|
+
0-based ordinal for non-PDF multi-output operations (e.g. frame
|
|
2811
|
+
strip, chapter split). Mutually exclusive with `page_index`.
|
|
2812
|
+
Per ADR-0009 §D2.
|
|
2813
|
+
example: 0
|
|
2814
|
+
|
|
2815
|
+
# ============================================
|
|
2816
|
+
# WORKFLOW STATE CHANGED (per ticket I24)
|
|
2817
|
+
# ============================================
|
|
2818
|
+
|
|
2819
|
+
WorkflowStateChanged:
|
|
2820
|
+
type: object
|
|
2821
|
+
description: |
|
|
2822
|
+
Workflow-level state-transition event published by the API
|
|
2823
|
+
when a workflow's `status` changes. Per ticket
|
|
2824
|
+
[I24 `e50uXLcl`](https://trello.com/c/e50uXLcl) + plan v5
|
|
2825
|
+
round 9.
|
|
2826
|
+
|
|
2827
|
+
Emitted on every transition (e.g. `pending → in_progress`,
|
|
2828
|
+
`in_progress → paused_insufficient_credits`,
|
|
2829
|
+
`paused_insufficient_credits → in_progress` after resume,
|
|
2830
|
+
`in_progress → cancelled`, `paused_insufficient_credits →
|
|
2831
|
+
expired`, the terminal `completed` / `failed` /
|
|
2832
|
+
`partially_failed`). The SSE stream's
|
|
2833
|
+
`workflow.completed` / `workflow.failed` /
|
|
2834
|
+
`workflow.partially_failed` events are the frontend-facing
|
|
2835
|
+
subset of these transitions; this event covers the full
|
|
2836
|
+
lifecycle for backend consumers (audit log, dashboards,
|
|
2837
|
+
webhook subscribers).
|
|
2838
|
+
|
|
2839
|
+
`reason` is a free-form string carrying advisory cause —
|
|
2840
|
+
same opacity precedent as `OperationMetrics.re_encode_reason`
|
|
2841
|
+
(per I16-CONS) and `SseWorkflowTerminalData.reason` (per
|
|
2842
|
+
I27). `billing_effect` is present only on transitions to
|
|
2843
|
+
`cancelled` or `expired` — both states release any unspent
|
|
2844
|
+
reservation portion (see `WorkflowCancelBillingEffect` in
|
|
2845
|
+
`openapi/api.yaml`).
|
|
2846
|
+
required:
|
|
2847
|
+
- workflow_id
|
|
2848
|
+
- previous_status
|
|
2849
|
+
- current_status
|
|
2850
|
+
- changed_at
|
|
2851
|
+
properties:
|
|
2852
|
+
workflow_id:
|
|
2853
|
+
type: string
|
|
2854
|
+
format: uuid
|
|
2855
|
+
description: UUID-v7 workflow identifier.
|
|
2856
|
+
previous_status:
|
|
2857
|
+
type: string
|
|
2858
|
+
enum:
|
|
2859
|
+
- pending
|
|
2860
|
+
- in_progress
|
|
2861
|
+
- completed
|
|
2862
|
+
- failed
|
|
2863
|
+
- partially_failed
|
|
2864
|
+
- paused_insufficient_credits
|
|
2865
|
+
- cancelled
|
|
2866
|
+
- expired
|
|
2867
|
+
current_status:
|
|
2868
|
+
type: string
|
|
2869
|
+
enum:
|
|
2870
|
+
- pending
|
|
2871
|
+
- in_progress
|
|
2872
|
+
- completed
|
|
2873
|
+
- failed
|
|
2874
|
+
- partially_failed
|
|
2875
|
+
- paused_insufficient_credits
|
|
2876
|
+
- cancelled
|
|
2877
|
+
- expired
|
|
2878
|
+
changed_at:
|
|
2879
|
+
type: string
|
|
2880
|
+
format: date-time
|
|
2881
|
+
reason:
|
|
2882
|
+
type: string
|
|
2883
|
+
description: |
|
|
2884
|
+
Optional advisory reason. Free-form string; not enumerated.
|
|
2885
|
+
Examples: `all jobs completed successfully`,
|
|
2886
|
+
`next reservation exceeded available_credits` (when
|
|
2887
|
+
transitioning to `paused_insufficient_credits`),
|
|
2888
|
+
`caller requested cancel`, `paused_insufficient_credits
|
|
2889
|
+
past expires_at`, `dispatch timeout`.
|
|
2890
|
+
billing_effect:
|
|
2891
|
+
type: string
|
|
2892
|
+
enum:
|
|
2893
|
+
- unspent_reservation_released
|
|
2894
|
+
- none
|
|
2895
|
+
description: |
|
|
2896
|
+
Present on transitions to `cancelled` or `expired`.
|
|
2897
|
+
Mirrors `WorkflowCancelBillingEffect` from
|
|
2898
|
+
`openapi/api.yaml`. Absent on other transitions.
|
|
2899
|
+
|
|
2900
|
+
# ============================================
|
|
2901
|
+
# METRICS
|
|
2902
|
+
# ============================================
|
|
2903
|
+
|
|
2904
|
+
OperationMetrics:
|
|
2905
|
+
type: object
|
|
2906
|
+
description: |
|
|
2907
|
+
Operation-specific metrics. Content varies by operation type.
|
|
2908
|
+
All metrics include duration_ms. Compression includes size/ratio.
|
|
2909
|
+
Merge includes input count. Archive includes file count and total size.
|
|
2910
|
+
properties:
|
|
2911
|
+
original_size_bytes:
|
|
2912
|
+
type: integer
|
|
2913
|
+
format: int64
|
|
2914
|
+
description: Original file size in bytes (compress, convert, thumbnail, image_watermark, text_watermark)
|
|
2915
|
+
example: 5242880
|
|
2916
|
+
output_size_bytes:
|
|
2917
|
+
type: integer
|
|
2918
|
+
format: int64
|
|
2919
|
+
description: Output file size in bytes
|
|
2920
|
+
example: 2097152
|
|
2921
|
+
compression_ratio:
|
|
2922
|
+
type: number
|
|
2923
|
+
format: float
|
|
2924
|
+
minimum: 0
|
|
2925
|
+
maximum: 1
|
|
2926
|
+
description: |
|
|
2927
|
+
Ratio of output to original size (0.0 to 1.0, lower = more compression).
|
|
2928
|
+
Only present for compress operations.
|
|
2929
|
+
example: 0.40
|
|
2930
|
+
duration_ms:
|
|
2931
|
+
type: integer
|
|
2932
|
+
format: int64
|
|
2933
|
+
description: Total processing time in milliseconds
|
|
2934
|
+
example: 1500
|
|
2935
|
+
input_count:
|
|
2936
|
+
type: integer
|
|
2937
|
+
description: Number of input files (merge, archive)
|
|
2938
|
+
example: 3
|
|
2939
|
+
file_count:
|
|
2940
|
+
type: integer
|
|
2941
|
+
description: Number of files in archive (archive only)
|
|
2942
|
+
example: 30
|
|
2943
|
+
total_input_size_bytes:
|
|
2944
|
+
type: integer
|
|
2945
|
+
format: int64
|
|
2946
|
+
description: Sum of all input file sizes (merge, archive)
|
|
2947
|
+
example: 52428800
|
|
2948
|
+
re_encode_decision:
|
|
2949
|
+
# Named schema lifted from inline per ticket QokFw8VR.
|
|
2950
|
+
$ref: '#/components/schemas/ReEncodeDecision'
|
|
2951
|
+
re_encode_reason:
|
|
2952
|
+
type: string
|
|
2953
|
+
description: |
|
|
2954
|
+
Advisory explanation for `re_encode_decision` (e.g.
|
|
2955
|
+
`all_inputs_compatible`, `explicit_always_mode`,
|
|
2956
|
+
`input_codec_mismatch`, `input_framerate_mismatch`).
|
|
2957
|
+
Free-form string — not an enum — so the Lambda can emit
|
|
2958
|
+
human-readable diagnostics that evolve without contract
|
|
2959
|
+
churn (compatibility-probe algorithm stays opaque per
|
|
2960
|
+
plan v5 §F8.2). Per ticket I16-CONS.
|
|
2961
|
+
example: input_codec_mismatch
|
|
2962
|
+
|
|
2963
|
+
# ============================================
|
|
2964
|
+
# UPLOAD PROBE PAYLOADS (per ticket vBlEurU7)
|
|
2965
|
+
# ============================================
|
|
2966
|
+
|
|
2967
|
+
UploadProbeRequest:
|
|
2968
|
+
type: object
|
|
2969
|
+
description: |
|
|
2970
|
+
Request payload for the upload-probe Lambda. Shared between
|
|
2971
|
+
the synchronous Lambda RequestResponse path (backing
|
|
2972
|
+
`POST /api/uploads/{id}/probe`) and the asynchronous
|
|
2973
|
+
SNS->SQS->Lambda path (eager `rich_metadata` enrichment on
|
|
2974
|
+
upload finalize). Per ticket
|
|
2975
|
+
[vBlEurU7](https://trello.com/c/vBlEurU7) +
|
|
2976
|
+
[rdBHmTfa](https://trello.com/c/rdBHmTfa).
|
|
2977
|
+
|
|
2978
|
+
The Lambda detects which path it is on from the AWS event
|
|
2979
|
+
source structure — there is no flag in the payload that
|
|
2980
|
+
distinguishes sync vs async. The shape is intentionally
|
|
2981
|
+
small so SDK generators emit a single typed binding the API
|
|
2982
|
+
layer can construct from either invocation path.
|
|
2983
|
+
required:
|
|
2984
|
+
- file_id
|
|
2985
|
+
- source_bucket
|
|
2986
|
+
- source_key
|
|
2987
|
+
- file_type
|
|
2988
|
+
- idempotency_key
|
|
2989
|
+
properties:
|
|
2990
|
+
file_id:
|
|
2991
|
+
type: string
|
|
2992
|
+
format: uuid
|
|
2993
|
+
description: |
|
|
2994
|
+
Upload file identifier (UUID v7). Mirrors the path
|
|
2995
|
+
parameter on `POST /api/uploads/{id}/probe` for the sync
|
|
2996
|
+
path and the upload row's primary key for the async path.
|
|
2997
|
+
example: "019539ab-1111-7000-8000-000000000010"
|
|
2998
|
+
source_bucket:
|
|
2999
|
+
type: string
|
|
3000
|
+
description: |
|
|
3001
|
+
S3 bucket containing the uploaded file. Always the
|
|
3002
|
+
tenant-scoped input bucket
|
|
3003
|
+
(`gisl-{env}-{region}-input`).
|
|
3004
|
+
example: "gisl-stg-euw1-input"
|
|
3005
|
+
source_key:
|
|
3006
|
+
type: string
|
|
3007
|
+
description: |
|
|
3008
|
+
S3 key of the uploaded file under `source_bucket`.
|
|
3009
|
+
example: "uploads/019539ab-1111-7000-8000-000000000010/clip.mp4"
|
|
3010
|
+
file_type:
|
|
3011
|
+
type: string
|
|
3012
|
+
description: |
|
|
3013
|
+
MIME type of the uploaded file (e.g. `video/mp4`,
|
|
3014
|
+
`audio/mpeg`, `application/pdf`) as recorded on the
|
|
3015
|
+
upload row at finalize time. Field name follows the
|
|
3016
|
+
AsyncAPI events.yaml convention (`OperationRequest.file_type`
|
|
3017
|
+
and the rest of the message-payload schemas in this spec
|
|
3018
|
+
consistently use `file_type` for MIME, even though
|
|
3019
|
+
`openapi/api.yaml` uses `mime_type` for the same concept
|
|
3020
|
+
on the REST surface). The probe uses this as a hint for
|
|
3021
|
+
which extractor pipeline to run; mismatches against the
|
|
3022
|
+
actual container surface as `format_mismatch` in the
|
|
3023
|
+
completion's `error_code`.
|
|
3024
|
+
example: "video/mp4"
|
|
3025
|
+
idempotency_key:
|
|
3026
|
+
type: string
|
|
3027
|
+
minLength: 1
|
|
3028
|
+
maxLength: 200
|
|
3029
|
+
description: |
|
|
3030
|
+
Caller-supplied idempotency token. Echoed back on the
|
|
3031
|
+
`UploadProbeCompletion` (async branch) so the API
|
|
3032
|
+
consumer can deduplicate against the upload row.
|
|
3033
|
+
|
|
3034
|
+
Conventions:
|
|
3035
|
+
- Sync path: typically the `file_id` itself, since the
|
|
3036
|
+
probe is cached server-side per upload (see
|
|
3037
|
+
`UploadProbeMediaMetadata.probed_at` description in
|
|
3038
|
+
`openapi/api.yaml`).
|
|
3039
|
+
- Async path: the upload finalize event identifier
|
|
3040
|
+
(e.g. `upload-finalize:{file_id}`) so retries of the
|
|
3041
|
+
same finalize event collapse to a single completion.
|
|
3042
|
+
example: "upload-finalize:019539ab-1111-7000-8000-000000000010"
|
|
3043
|
+
requested_at:
|
|
3044
|
+
type: string
|
|
3045
|
+
format: date-time
|
|
3046
|
+
description: |
|
|
3047
|
+
ISO-8601 timestamp at which the probe request was issued.
|
|
3048
|
+
Optional; populated when the API publisher records it
|
|
3049
|
+
for log correlation. Not used by the Lambda for any
|
|
3050
|
+
decision.
|
|
3051
|
+
example: "2026-05-06T13:50:00Z"
|
|
3052
|
+
|
|
3053
|
+
UploadProbeCompletion:
|
|
3054
|
+
type: object
|
|
3055
|
+
description: |
|
|
3056
|
+
Completion payload published by the upload-probe Lambda to
|
|
3057
|
+
the `upload-probe-completions` SQS queue on the async
|
|
3058
|
+
branch. Mirrors `UploadProbeResponse` (`openapi/api.yaml`)
|
|
3059
|
+
for the success case and additionally carries failure
|
|
3060
|
+
fields (`error_code`, `error_message`) so the API consumer
|
|
3061
|
+
can persist Lambda-side failures (S3 download failed,
|
|
3062
|
+
decoder crashed, etc.) on the upload row alongside
|
|
3063
|
+
successful probes.
|
|
3064
|
+
|
|
3065
|
+
**Conditional schema (mirrors `OperationResult`):**
|
|
3066
|
+
- When `error_code` is **absent**, the payload is treated as
|
|
3067
|
+
a successful probe and `probe_status`,
|
|
3068
|
+
`processing_class_pre_assignment`, and `media_metadata`
|
|
3069
|
+
are REQUIRED.
|
|
3070
|
+
- When `error_code` is **present**, the payload is treated as
|
|
3071
|
+
a Lambda-side failure and only `error_code` +
|
|
3072
|
+
`error_message` are REQUIRED on top of the always-required
|
|
3073
|
+
identification + provenance fields. `probe_status` and
|
|
3074
|
+
peers MAY be absent in this case.
|
|
3075
|
+
|
|
3076
|
+
Note that `probe_status: corrupt` / `unsupported_codec` /
|
|
3077
|
+
`missing_metadata` are **successful** probes that report an
|
|
3078
|
+
unhealthy file — they do NOT populate `error_code`. Reserve
|
|
3079
|
+
`error_code` for "the probe pipeline itself failed".
|
|
3080
|
+
|
|
3081
|
+
Sync invocations do not produce this shape — they return
|
|
3082
|
+
`UploadProbeResponse` directly.
|
|
3083
|
+
required:
|
|
3084
|
+
- file_id
|
|
3085
|
+
- idempotency_key
|
|
3086
|
+
- probed_at
|
|
3087
|
+
- probe_version
|
|
3088
|
+
if:
|
|
3089
|
+
not:
|
|
3090
|
+
required:
|
|
3091
|
+
- error_code
|
|
3092
|
+
then:
|
|
3093
|
+
required:
|
|
3094
|
+
- probe_status
|
|
3095
|
+
- processing_class_pre_assignment
|
|
3096
|
+
- media_metadata
|
|
3097
|
+
else:
|
|
3098
|
+
required:
|
|
3099
|
+
- error_code
|
|
3100
|
+
- error_message
|
|
3101
|
+
properties:
|
|
3102
|
+
file_id:
|
|
3103
|
+
type: string
|
|
3104
|
+
format: uuid
|
|
3105
|
+
description: Upload file identifier (UUID v7) — correlation key.
|
|
3106
|
+
example: "019539ab-1111-7000-8000-000000000010"
|
|
3107
|
+
idempotency_key:
|
|
3108
|
+
type: string
|
|
3109
|
+
description: |
|
|
3110
|
+
Echoed from the originating `UploadProbeRequest` for
|
|
3111
|
+
deduplication on the API consumer side.
|
|
3112
|
+
example: "upload-finalize:019539ab-1111-7000-8000-000000000010"
|
|
3113
|
+
probe_status:
|
|
3114
|
+
$ref: '#/components/schemas/UploadProbeStatus'
|
|
3115
|
+
processing_class_pre_assignment:
|
|
3116
|
+
$ref: '#/components/schemas/UploadProbeProcessingClass'
|
|
3117
|
+
media_metadata:
|
|
3118
|
+
$ref: '#/components/schemas/UploadProbeMediaMetadata'
|
|
3119
|
+
error_code:
|
|
3120
|
+
type: string
|
|
3121
|
+
description: |
|
|
3122
|
+
Machine-readable error code when the probe pipeline
|
|
3123
|
+
itself failed. Reuses the same vocabulary as
|
|
3124
|
+
`OperationResult.error_code` where applicable
|
|
3125
|
+
(`s3_download_failed`, `s3_access_denied`, `timeout`,
|
|
3126
|
+
`out_of_memory`, `decode_failed`, `processing_failed`,
|
|
3127
|
+
`unknown`). Absent on successful probes — including
|
|
3128
|
+
probes that report `probe_status: corrupt /
|
|
3129
|
+
unsupported_codec / missing_metadata`, which are
|
|
3130
|
+
successful probes about an unhealthy file.
|
|
3131
|
+
example: "s3_download_failed"
|
|
3132
|
+
error_message:
|
|
3133
|
+
type: string
|
|
3134
|
+
description: |
|
|
3135
|
+
Human-readable error message paired with `error_code`.
|
|
3136
|
+
Absent on successful probes.
|
|
3137
|
+
example: "Failed to download source file from S3"
|
|
3138
|
+
probed_at:
|
|
3139
|
+
type: string
|
|
3140
|
+
format: date-time
|
|
3141
|
+
description: |
|
|
3142
|
+
ISO-8601 timestamp at which the probe ran (or attempted
|
|
3143
|
+
to run, for failure cases). Always present so the API
|
|
3144
|
+
consumer can timestamp the upload row regardless of
|
|
3145
|
+
outcome. For successful probes this matches
|
|
3146
|
+
`media_metadata.probed_at`; the duplicate top-level
|
|
3147
|
+
field exists so the failure case can still carry a
|
|
3148
|
+
timestamp even when `media_metadata` is omitted.
|
|
3149
|
+
example: "2026-05-06T13:50:01Z"
|
|
3150
|
+
probe_version:
|
|
3151
|
+
type: string
|
|
3152
|
+
description: |
|
|
3153
|
+
Semver of the upload-probe Lambda implementation that
|
|
3154
|
+
produced this completion. Useful for cache invalidation
|
|
3155
|
+
on the API side (re-probe when the prober ships a new
|
|
3156
|
+
extractor) and for log correlation.
|
|
3157
|
+
example: "1.0.0"
|
|
3158
|
+
|
|
3159
|
+
UploadProbeStatus:
|
|
3160
|
+
type: string
|
|
3161
|
+
description: |
|
|
3162
|
+
Outcome of a successful preflight probe. Mirrors
|
|
3163
|
+
`UploadProbeStatus` in `openapi/api.yaml` so SDK generators
|
|
3164
|
+
consuming both specs emit a single typed binding.
|
|
3165
|
+
|
|
3166
|
+
Cross-spec parity is verified by
|
|
3167
|
+
`tests/test_upload_probe_schemas.py` — the OpenAPI side is
|
|
3168
|
+
the source of truth for the value set.
|
|
3169
|
+
|
|
3170
|
+
Note: a `probe_status` value here means the probe pipeline
|
|
3171
|
+
succeeded. Lambda-side failures on the async branch are
|
|
3172
|
+
signalled via `UploadProbeCompletion.error_code` and do not
|
|
3173
|
+
require populating this field.
|
|
3174
|
+
enum:
|
|
3175
|
+
- ok
|
|
3176
|
+
- corrupt
|
|
3177
|
+
- unsupported_codec
|
|
3178
|
+
- missing_metadata
|
|
3179
|
+
|
|
3180
|
+
UploadProbeProcessingClass:
|
|
3181
|
+
type: string
|
|
3182
|
+
description: |
|
|
3183
|
+
Tier-aware pre-assignment. Mirrors
|
|
3184
|
+
`UploadProbeProcessingClass` in `openapi/api.yaml` so SDK
|
|
3185
|
+
generators consuming both specs emit a single typed binding.
|
|
3186
|
+
|
|
3187
|
+
Cross-spec parity is verified by
|
|
3188
|
+
`tests/test_upload_probe_schemas.py` — the OpenAPI side is
|
|
3189
|
+
the source of truth for the value set.
|
|
3190
|
+
enum:
|
|
3191
|
+
- short_form
|
|
3192
|
+
- long_form
|
|
3193
|
+
- blocked
|
|
3194
|
+
|
|
3195
|
+
UploadProbeMediaMetadata:
|
|
3196
|
+
type: object
|
|
3197
|
+
description: |
|
|
3198
|
+
Probe-extracted media metadata. Mirrors
|
|
3199
|
+
`UploadProbeMediaMetadata` in `openapi/api.yaml` so SDK
|
|
3200
|
+
generators consuming both specs emit a single typed binding
|
|
3201
|
+
instead of two `AnonymousSchema_N` placeholders.
|
|
3202
|
+
|
|
3203
|
+
AsyncAPI 3.0 cannot `$ref` across files into the OpenAPI
|
|
3204
|
+
spec, so the shape is duplicated here verbatim. Cross-spec
|
|
3205
|
+
parity is verified by
|
|
3206
|
+
`tests/test_upload_probe_schemas.py` — the OpenAPI side is
|
|
3207
|
+
the source of truth.
|
|
3208
|
+
|
|
3209
|
+
Schema covers the **union** of fields needed by the API's
|
|
3210
|
+
`MetadataResponse` projection across video / audio /
|
|
3211
|
+
document inputs (per the M2 Epic re-scope —
|
|
3212
|
+
[`SrHwuvIl`](https://trello.com/c/SrHwuvIl) — which makes
|
|
3213
|
+
this probe Lambda the universal non-image metadata source
|
|
3214
|
+
feeding `rich_metadata`). The Lambda extractor only
|
|
3215
|
+
populates fields it can derive from the actual container;
|
|
3216
|
+
unrelated fields are simply omitted (absent fields are NOT
|
|
3217
|
+
errors — they reflect "this metadata is not applicable /
|
|
3218
|
+
not extractable" rather than "this metadata failed
|
|
3219
|
+
validation"). `probed_at` is always present.
|
|
3220
|
+
required:
|
|
3221
|
+
- probed_at
|
|
3222
|
+
properties:
|
|
3223
|
+
duration_seconds:
|
|
3224
|
+
type: integer
|
|
3225
|
+
minimum: 0
|
|
3226
|
+
description: Container-reported duration (audio + video).
|
|
3227
|
+
width:
|
|
3228
|
+
type: integer
|
|
3229
|
+
minimum: 1
|
|
3230
|
+
description: Pixel width (image + video; best-effort document).
|
|
3231
|
+
height:
|
|
3232
|
+
type: integer
|
|
3233
|
+
minimum: 1
|
|
3234
|
+
description: Pixel height (image + video; best-effort document).
|
|
3235
|
+
codec:
|
|
3236
|
+
type: string
|
|
3237
|
+
description: |
|
|
3238
|
+
Primary codec identifier as reported by the prober. For
|
|
3239
|
+
video inputs this is the **video** codec; for audio-only
|
|
3240
|
+
inputs this is the audio codec. For video files with
|
|
3241
|
+
audio tracks, the audio codec is reported separately as
|
|
3242
|
+
`audio_codec`. Examples: `h264`, `h265`, `vp9`, `av1`,
|
|
3243
|
+
`aac`, `opus`, `mp3`. Not constrained to an enum — codec
|
|
3244
|
+
strings evolve with FFmpeg releases (per ADR-0007 FFmpeg
|
|
3245
|
+
pin) and SDKs should string-match.
|
|
3246
|
+
audio_codec:
|
|
3247
|
+
type: string
|
|
3248
|
+
description: |
|
|
3249
|
+
Audio codec for video files that carry an audio track.
|
|
3250
|
+
Distinct from `codec` (which is the video codec for
|
|
3251
|
+
video inputs). Absent for video-only / silent video
|
|
3252
|
+
inputs and for audio-only inputs (audio-only inputs put
|
|
3253
|
+
their codec under `codec`).
|
|
3254
|
+
container:
|
|
3255
|
+
type: string
|
|
3256
|
+
description: |
|
|
3257
|
+
Container format. Examples: `mp4`, `webm`, `mov`,
|
|
3258
|
+
`mkv`, `mp3`, `wav`, `flac`. Not constrained to an
|
|
3259
|
+
enum.
|
|
3260
|
+
fps:
|
|
3261
|
+
type: number
|
|
3262
|
+
minimum: 0
|
|
3263
|
+
description: |
|
|
3264
|
+
Container-reported frame rate (video only). Number, not
|
|
3265
|
+
integer — frame rates are commonly fractional (e.g.
|
|
3266
|
+
`29.97`, `23.976`).
|
|
3267
|
+
bitrate_bps:
|
|
3268
|
+
type: integer
|
|
3269
|
+
minimum: 0
|
|
3270
|
+
description: |
|
|
3271
|
+
Overall stream bitrate, **bits per second**. Units in
|
|
3272
|
+
the field name, mirroring `duration_seconds`, so SDKs
|
|
3273
|
+
avoid the kbps-vs-bps guessing trap. Container-reported
|
|
3274
|
+
for video + audio.
|
|
3275
|
+
audio_layout:
|
|
3276
|
+
type: string
|
|
3277
|
+
description: |
|
|
3278
|
+
Channel layout, human-display form. Examples: `mono`,
|
|
3279
|
+
`stereo`, `5.1`, `7.1`. Not constrained. Pairs with the
|
|
3280
|
+
numeric `channels` field (which is what API consumers
|
|
3281
|
+
project into `rich_metadata`); `audio_layout` is
|
|
3282
|
+
preserved on the probe row for UI display ("5.1
|
|
3283
|
+
surround") without forcing the UI to derive a label
|
|
3284
|
+
from the integer.
|
|
3285
|
+
channels:
|
|
3286
|
+
type: integer
|
|
3287
|
+
minimum: 1
|
|
3288
|
+
description: |
|
|
3289
|
+
Numeric audio channel count derived by the Lambda from
|
|
3290
|
+
ffprobe output. Examples: `1` (mono), `2` (stereo), `6`
|
|
3291
|
+
(5.1), `8` (7.1). Pairs with `audio_layout`. Audio +
|
|
3292
|
+
video.
|
|
3293
|
+
sample_rate_hz:
|
|
3294
|
+
type: integer
|
|
3295
|
+
minimum: 1
|
|
3296
|
+
description: |
|
|
3297
|
+
Audio sample rate, **Hertz**. Units in the field name,
|
|
3298
|
+
mirroring `duration_seconds` / `bitrate_bps`. Examples:
|
|
3299
|
+
`44100`, `48000`. Audio + video-with-audio.
|
|
3300
|
+
page_count:
|
|
3301
|
+
type: integer
|
|
3302
|
+
minimum: 0
|
|
3303
|
+
description: |
|
|
3304
|
+
Document page count (PDF / EPUB / DOCX / XLSX / PPTX /
|
|
3305
|
+
ODT / ODS / ODP). `0` for a document the prober opened
|
|
3306
|
+
but found empty.
|
|
3307
|
+
dpi:
|
|
3308
|
+
type: integer
|
|
3309
|
+
minimum: 1
|
|
3310
|
+
description: |
|
|
3311
|
+
Document resolution, single-axis (dots per inch).
|
|
3312
|
+
Single-axis matches the existing `MetadataResponse`
|
|
3313
|
+
contract on the OpenAPI side; the prober reports the
|
|
3314
|
+
page-1 horizontal DPI when the document declares it,
|
|
3315
|
+
otherwise omits the field.
|
|
3316
|
+
probed_at:
|
|
3317
|
+
type: string
|
|
3318
|
+
format: date-time
|
|
3319
|
+
description: |
|
|
3320
|
+
ISO-8601 timestamp at which the probe ran. Idempotent
|
|
3321
|
+
for the same `file_id` — subsequent probe calls return
|
|
3322
|
+
the cached `probed_at`.
|
|
3323
|
+
|
|
3324
|
+
# ============================================
|
|
3325
|
+
# ENUMS
|
|
3326
|
+
# ============================================
|
|
3327
|
+
|
|
3328
|
+
OperationType:
|
|
3329
|
+
type: string
|
|
3330
|
+
description: |
|
|
3331
|
+
Operation type as carried inside the message **payload** body. This
|
|
3332
|
+
enum is deliberately narrower than the SNS `operation_type`
|
|
3333
|
+
MessageAttribute: the attribute enum permits per-media thumbnail
|
|
3334
|
+
sub-types (`thumbnail_image`, `thumbnail_video`,
|
|
3335
|
+
`thumbnail_document`, `thumbnail_office`) for routing on the
|
|
3336
|
+
`operations` topic, but the payload body always carries the
|
|
3337
|
+
semantic base value (`thumbnail`). See
|
|
3338
|
+
`OperationRequestAttributes.operation_type` for the broader
|
|
3339
|
+
attribute enum and the routing contract. Note that the attribute
|
|
3340
|
+
values the publisher currently emits are governed by the
|
|
3341
|
+
thumbnail migration-window note (top-level `info.description`
|
|
3342
|
+
and `OperationRequestMessage.description`).
|
|
3343
|
+
|
|
3344
|
+
Compression operations are routed by `job_type` on the separate
|
|
3345
|
+
`job-requests` topic — see `JobRequestAttributes` and the top-level
|
|
3346
|
+
`info.description`.
|
|
3347
|
+
|
|
3348
|
+
- `compress`: Reduce file size (image, video, audio, document).
|
|
3349
|
+
Routes via `job_type` on the `job-requests` topic.
|
|
3350
|
+
- `thumbnail`: Thumbnail generation. The payload always carries
|
|
3351
|
+
the base value; the SNS `operation_type` attribute enum
|
|
3352
|
+
additionally permits one of the four sub-type values
|
|
3353
|
+
(`thumbnail_image`, `thumbnail_video`, `thumbnail_document`,
|
|
3354
|
+
`thumbnail_office`) for routing the request to the matching
|
|
3355
|
+
per-media Lambda. During the migration window, the legacy
|
|
3356
|
+
`operation_type=thumbnail` attribute value also remains a
|
|
3357
|
+
valid routing target (to `ops-thumbnail`). See the
|
|
3358
|
+
migration-window note for which values the publisher currently
|
|
3359
|
+
emits.
|
|
3360
|
+
- `image_watermark`: Apply image overlay (file or external_source)
|
|
3361
|
+
onto a base media asset (Path B multi-input with role
|
|
3362
|
+
base+overlay per JobInputV2.role). Stable for static-image bases
|
|
3363
|
+
(image/jpeg, image/png, image/webp); animated GIF and video
|
|
3364
|
+
bases are advertised in `image_watermark.yaml` as `planned` via
|
|
3365
|
+
parallel mime_groups (`image_gif`, `video`) — dispatch returns
|
|
3366
|
+
`feature_not_available` (422) until Lambda support ships.
|
|
3367
|
+
Routes via `operation_type=image_watermark` to
|
|
3368
|
+
`ops-image-watermark`. Per ADR-0004 + I4-CONS + I5 (Trello
|
|
3369
|
+
AKZiOXnd).
|
|
3370
|
+
- `text_watermark`: Render a text overlay (Liberation Sans) onto
|
|
3371
|
+
an image. Single-input. Routes via
|
|
3372
|
+
`operation_type=text_watermark` to `ops-text-watermark`.
|
|
3373
|
+
Per ADR-0004 + I4-CONS.
|
|
3374
|
+
- `convert`: Change file format (image, video, audio, document).
|
|
3375
|
+
Routes via `operation_type=convert` to `ops-convert`.
|
|
3376
|
+
- `merge`: Concatenate/combine multiple files (image, video,
|
|
3377
|
+
audio). Image inputs merge into animated GIF or slideshow
|
|
3378
|
+
video; image collage/grid and PDF concatenation are not
|
|
3379
|
+
supported by the V1 Lambda. Routes via `operation_type=merge`
|
|
3380
|
+
to `ops-merge`. A single Lambda handles the supported merge
|
|
3381
|
+
output types.
|
|
3382
|
+
- `archive`: Bundle files into ZIP/tar.gz (media-agnostic).
|
|
3383
|
+
Routes via `operation_type=archive` to `ops-archive`. No
|
|
3384
|
+
`media_group` attribute is set for archive.
|
|
3385
|
+
- `custom_luma`: Apply a caller-uploaded luma matte to a base
|
|
3386
|
+
video for a custom luma-matte transition effect. Multi-input
|
|
3387
|
+
(Path B with `role: base` + `role: transition_mask` per
|
|
3388
|
+
`JobInputV2.role`). `availability: planned` +
|
|
3389
|
+
`required_tier: pro` per the operation schema; the API
|
|
3390
|
+
rejects workflow-create with `feature_not_available` (422)
|
|
3391
|
+
until the Lambda ships, so traffic does not reach SNS today.
|
|
3392
|
+
When Lambda support lands, routes via
|
|
3393
|
+
`operation_type=custom_luma` to `ops-custom-luma`. Per ADR-
|
|
3394
|
+
0004 + I29 (Trello EPUE5Vs1).
|
|
3395
|
+
- `audio_overlay`: Mix a secondary audio asset over a primary
|
|
3396
|
+
audio or video base (DJ tags, podcast intros/outros, station
|
|
3397
|
+
IDs, jingles). Multi-input (Path B with `role: base` +
|
|
3398
|
+
`role: overlay` per `JobInputV2.role`). Both mime_groups
|
|
3399
|
+
(`audio`, `video`) are `availability: planned` per the
|
|
3400
|
+
operation schema; the API rejects workflow-create with
|
|
3401
|
+
`feature_not_available` (422) until the Lambda ships, so
|
|
3402
|
+
traffic does not reach SNS today. **NOT** the same as
|
|
3403
|
+
`audio_watermark` (steganographic, owned by I20). Per ADR-
|
|
3404
|
+
0004 + I19 (Trello Xr3Z4GBF).
|
|
3405
|
+
- `audio_watermark`: Embed a steganographic forensic watermark
|
|
3406
|
+
into an audio asset (or a video's audio track) — Cinavia /
|
|
3407
|
+
Resemble PerTh territory. Single-input. Both mime_groups
|
|
3408
|
+
(`audio`, `video` — embed in video's audio track) are
|
|
3409
|
+
`availability: planned` + `required_tier: enterprise` per
|
|
3410
|
+
the operation schema; the API rejects workflow-create with
|
|
3411
|
+
`feature_not_available` (422) + `feature_tier_restricted`
|
|
3412
|
+
(403) until the Lambda ships, so traffic does not reach SNS
|
|
3413
|
+
today. Pairs with `POST /api/audio-watermark/decode` for
|
|
3414
|
+
own-watermarks-only extraction. Per ADR-0004 + I20 (Trello
|
|
3415
|
+
omiCq7Vn).
|
|
3416
|
+
enum:
|
|
3417
|
+
- compress
|
|
3418
|
+
- thumbnail
|
|
3419
|
+
- image_watermark
|
|
3420
|
+
- text_watermark
|
|
3421
|
+
- convert
|
|
3422
|
+
- merge
|
|
3423
|
+
- archive
|
|
3424
|
+
- custom_luma
|
|
3425
|
+
- audio_overlay
|
|
3426
|
+
- audio_watermark
|
|
3427
|
+
|
|
3428
|
+
MediaGroup:
|
|
3429
|
+
type: string
|
|
3430
|
+
description: |
|
|
3431
|
+
Media category. Used as an **informational** SNS message attribute
|
|
3432
|
+
on the `operations` topic only — preserved for consumer
|
|
3433
|
+
observability and log correlation, and **not** used by SNS as a
|
|
3434
|
+
routing filter. Routing on the `operations` topic is by
|
|
3435
|
+
`operation_type` alone; routing on the `job-requests` topic is by
|
|
3436
|
+
`job_type` (see `JobRequestAttributes`).
|
|
3437
|
+
|
|
3438
|
+
Derived by the publisher from MIME type prefix for single-input
|
|
3439
|
+
operations:
|
|
3440
|
+
- image/* -> image
|
|
3441
|
+
- video/* -> video
|
|
3442
|
+
- audio/* -> audio
|
|
3443
|
+
- document types -> document (PDF, EPUB, DOCX, XLSX, PPTX, ODT,
|
|
3444
|
+
ODS, ODP)
|
|
3445
|
+
|
|
3446
|
+
For merge, derived from `output_type`:
|
|
3447
|
+
- output_type=gif -> image
|
|
3448
|
+
- output_type=video -> video
|
|
3449
|
+
- output_type=audio -> audio
|
|
3450
|
+
|
|
3451
|
+
Omitted from the SNS attributes for archive (media-agnostic). The
|
|
3452
|
+
four thumbnail sub-types map to media_group as follows:
|
|
3453
|
+
- thumbnail_image -> image
|
|
3454
|
+
- thumbnail_video -> video
|
|
3455
|
+
- thumbnail_document -> document
|
|
3456
|
+
- thumbnail_office -> document (office files folded under
|
|
3457
|
+
`document` at the media_group level)
|
|
3458
|
+
enum:
|
|
3459
|
+
- image
|
|
3460
|
+
- video
|
|
3461
|
+
- audio
|
|
3462
|
+
- document
|
|
3463
|
+
|
|
3464
|
+
MergeOutputType:
|
|
3465
|
+
type: string
|
|
3466
|
+
description: |
|
|
3467
|
+
Output format for merge operations. All merge operations route to
|
|
3468
|
+
the single `ops-merge` Lambda via `operation_type=merge`
|
|
3469
|
+
regardless of the `output_type` value — `output_type` is read by
|
|
3470
|
+
the merge Lambda to decide the internal encoding path and output
|
|
3471
|
+
format, not to influence SNS routing.
|
|
3472
|
+
- `gif`: Animated GIF (ImageMagick convert inside the merge Lambda)
|
|
3473
|
+
- `video`: Slideshow from images or video concatenation (FFmpeg inside the merge Lambda)
|
|
3474
|
+
- `audio`: Audio concatenation (FFmpeg inside the merge Lambda)
|
|
3475
|
+
enum:
|
|
3476
|
+
- gif
|
|
3477
|
+
- video
|
|
3478
|
+
- audio
|
|
3479
|
+
|
|
3480
|
+
JobInputRole:
|
|
3481
|
+
type: string
|
|
3482
|
+
description: |
|
|
3483
|
+
Role for role-based multi-input operations. Mirrors
|
|
3484
|
+
`JobInputV2.role` in `openapi/api.yaml`:
|
|
3485
|
+
- `image_watermark`: REQUIRED on each entry — exactly
|
|
3486
|
+
one `base` + one `overlay` per job (per ticket I4-CONS).
|
|
3487
|
+
- `custom_luma`: REQUIRED — exactly one `base` + one
|
|
3488
|
+
`transition_mask` per job (per ticket I29).
|
|
3489
|
+
- `audio_overlay`: REQUIRED — exactly one `base` + one
|
|
3490
|
+
`overlay` per job (per ticket I19); reuses
|
|
3491
|
+
`image_watermark`'s role values.
|
|
3492
|
+
- `merge` / `archive`: omit (all inputs share the same
|
|
3493
|
+
role). Future operations may widen this enum.
|
|
3494
|
+
|
|
3495
|
+
Named-schema form lifted from inline at `SourceEntry.role`
|
|
3496
|
+
per ticket QokFw8VR. The OpenAPI side at `JobInputV2.role`
|
|
3497
|
+
remains an inline enum today — symmetric extraction tracked
|
|
3498
|
+
as a follow-up; value-set parity is verified by inspection
|
|
3499
|
+
(both lists must remain identical).
|
|
3500
|
+
enum:
|
|
3501
|
+
- base
|
|
3502
|
+
- overlay
|
|
3503
|
+
- transition_mask
|
|
3504
|
+
|
|
3505
|
+
ReEncodeDecision:
|
|
3506
|
+
type: string
|
|
3507
|
+
description: |
|
|
3508
|
+
Path chosen for `merge.video` when `re_encode_mode=auto`.
|
|
3509
|
+
Server reports the actual path so callers can see why
|
|
3510
|
+
`auto` took the slow path. Absent for non-`merge.video`
|
|
3511
|
+
operations and for `merge.video` when `re_encode_mode` is
|
|
3512
|
+
`always` or `never` (path was caller-fixed). Per ticket
|
|
3513
|
+
I16-CONS (Trello 7nCZXEru). Workflow-create-time surface
|
|
3514
|
+
on `processing_plan.jobs[]` lands with I15-CONS
|
|
3515
|
+
(Trello YZpBKzOM).
|
|
3516
|
+
|
|
3517
|
+
Named-schema form lifted from inline at
|
|
3518
|
+
`OperationMetrics.re_encode_decision` per ticket QokFw8VR.
|
|
3519
|
+
enum:
|
|
3520
|
+
- stream_copy
|
|
3521
|
+
- re_encode
|
|
3522
|
+
|
|
3523
|
+
ProgressStatus:
|
|
3524
|
+
type: string
|
|
3525
|
+
description: |
|
|
3526
|
+
Status values for progress updates (non-terminal). Backwards-
|
|
3527
|
+
compatibly extended for long-form video operations per ticket
|
|
3528
|
+
[I27 `1R3K3bsG`](https://trello.com/c/1R3K3bsG) + plan v5
|
|
3529
|
+
§F8.3 round 10 — the `probing` / `decoding` / `encoding`
|
|
3530
|
+
statuses give callers visibility into long-form jobs that
|
|
3531
|
+
internally process inputs sequentially without forcing
|
|
3532
|
+
callers to decompose into multiple jobs.
|
|
3533
|
+
|
|
3534
|
+
Non-long-form operations continue to emit only `started` /
|
|
3535
|
+
`downloading` / `processing` / `uploading` (the V1 pattern);
|
|
3536
|
+
clients that don't need phase visibility can ignore the new
|
|
3537
|
+
statuses without behavioural change.
|
|
3538
|
+
|
|
3539
|
+
- `started`: Lambda picked up the operation.
|
|
3540
|
+
- `downloading`: Downloading source file(s) from S3.
|
|
3541
|
+
- `probing`: Long-form video — server-side metadata probe
|
|
3542
|
+
on inputs (codec / container / framerate / resolution
|
|
3543
|
+
/ pixel-format detection driving `re_encode_decision`).
|
|
3544
|
+
Pairs with `phase_input_index` / `phase_total_inputs` so
|
|
3545
|
+
the frontend can render "probing input 2/4". Per I15-CONS
|
|
3546
|
+
/ I16-CONS.
|
|
3547
|
+
- `decoding`: Long-form video — decoding inputs ahead of
|
|
3548
|
+
the encode pass. Pairs with `phase_*` fields.
|
|
3549
|
+
- `processing`: Actively processing (compressing, merging,
|
|
3550
|
+
watermarking, etc.). The catch-all phase used by
|
|
3551
|
+
short-form operations and short-form-equivalent stages of
|
|
3552
|
+
long-form operations. May pair with `phase_*` fields when
|
|
3553
|
+
the operation is long-form.
|
|
3554
|
+
- `encoding`: Long-form video — explicit encode-pass status
|
|
3555
|
+
(vs the umbrella `processing`). Surfaces "encoding output
|
|
3556
|
+
42%" when the encode pass is long enough to deserve
|
|
3557
|
+
dedicated visibility. May pair with `phase_*` fields for
|
|
3558
|
+
multi-output operations.
|
|
3559
|
+
- `uploading`: Uploading result to S3.
|
|
3560
|
+
enum:
|
|
3561
|
+
- started
|
|
3562
|
+
- downloading
|
|
3563
|
+
- probing
|
|
3564
|
+
- decoding
|
|
3565
|
+
- processing
|
|
3566
|
+
- encoding
|
|
3567
|
+
- uploading
|
|
3568
|
+
|
|
3569
|
+
ResultStatus:
|
|
3570
|
+
type: string
|
|
3571
|
+
description: |
|
|
3572
|
+
Status values for operation results (terminal):
|
|
3573
|
+
- completed: Operation finished successfully
|
|
3574
|
+
- failed: Operation encountered an error
|
|
3575
|
+
enum:
|
|
3576
|
+
- completed
|
|
3577
|
+
- failed
|
|
3578
|
+
|
|
3579
|
+
ErrorCode:
|
|
3580
|
+
type: string
|
|
3581
|
+
description: |
|
|
3582
|
+
Machine-readable error code for categorization and retry logic.
|
|
3583
|
+
|
|
3584
|
+
**Retryable errors** (SQS will retry automatically):
|
|
3585
|
+
- s3_download_failed: Source file download failed
|
|
3586
|
+
- s3_upload_failed: Output file upload failed
|
|
3587
|
+
- s3_access_denied: Permission denied (might be temporary)
|
|
3588
|
+
- out_of_memory: Lambda ran out of memory
|
|
3589
|
+
- timeout: Lambda execution timed out
|
|
3590
|
+
|
|
3591
|
+
**Non-retryable errors** (message sent to DLQ):
|
|
3592
|
+
- invalid_format: Unsupported or corrupted file
|
|
3593
|
+
- format_mismatch: MIME type doesn't match content
|
|
3594
|
+
- decode_failed: Cannot decode/parse file
|
|
3595
|
+
- processing_failed: Processing library error
|
|
3596
|
+
- output_too_large: Output larger than original (compress only)
|
|
3597
|
+
- invalid_options: Invalid operation options
|
|
3598
|
+
- missing_source: Source file not found in S3
|
|
3599
|
+
- invalid_key: S3 key is malformed
|
|
3600
|
+
- invalid_request: Operation request validation failed
|
|
3601
|
+
- unknown: Unclassified error
|
|
3602
|
+
enum:
|
|
3603
|
+
- s3_download_failed
|
|
3604
|
+
- s3_upload_failed
|
|
3605
|
+
- s3_access_denied
|
|
3606
|
+
- out_of_memory
|
|
3607
|
+
- timeout
|
|
3608
|
+
- invalid_format
|
|
3609
|
+
- format_mismatch
|
|
3610
|
+
- decode_failed
|
|
3611
|
+
- processing_failed
|
|
3612
|
+
- output_too_large
|
|
3613
|
+
- invalid_options
|
|
3614
|
+
- missing_source
|
|
3615
|
+
- invalid_key
|
|
3616
|
+
- invalid_request
|
|
3617
|
+
- unknown
|