5.8 KiB
Holistic Rubric: Multi-Tenant Authorization in Background Workers
Task Summary
The goal is to audit and refactor background SQS worker handlers (voice-synthsizer-job-handler and voice-cloning-job-handler) and database service wrappers in potion-voice to enforce strict multi-tenant data isolation by scoping all MongoDB queries with userId. The solution must prevent cross-tenant IDOR vulnerabilities while preserving asynchronous execution dependency order, SQS queue lifecycle reliability, and robust error-handling recovery.
Ground Truth
- Queue Message Context: SQS messages for voice synthesis contain
job.salutationId,job.userAudioProfileId, andjob.userId, but do not conveyjob.recordingId. - Database Relationships:
RecordingSalutationrecords link asalutationIdto a parentrecordingId.recordingIdmust be extracted fromsalutationToUpdate.recordingIdafter resolving theRecordingSalutationdocument from MongoDB.
- Mongoose Query Standards:
- Primary and secondary model operations (
UserAudioProfile,VoiceCloning,Salutation,Job,Recording) must be scoped with{ _id, userId, deleted: false }. - Mongoose
findOneAndUpdateaccepts 3 arguments:findOneAndUpdate(conditions, update, options). Passing 5 arguments or placing query filters in theoptionsargument bypasses user scoping and causes updates to be ignored.
- Primary and secondary model operations (
- Queue & Async Lifecycle:
- SQS messages must remain in flight until speech synthesis, model artifact rendering, and S3 uploads complete successfully.
- Deleting messages via
sqs.deleteMessageFromSQSbefore task completion prevents SQS redelivery on failure, causing unrecoverable data loss.
- Error Status Updates:
- On error or authorization rejection, the worker must update MongoDB job/profile statuses to
'error'regardless of pre-authorization state flags.
- On error or authorization rejection, the worker must update MongoDB job/profile statuses to
Key AI Failure Modes (Meaningful Failures)
-
Failure Mode 1: Missing Utility Module Startup Crash (
MODULE_NOT_FOUND) The agent adds import statements likeconst { requireUserId, tenantFilter } = require('../worker_tenant')across worker files without creatingworker_tenant.jsorworker_tenant/index.jsin the repository. At runtime, Node.js throwsError: Cannot find module '../worker_tenant', causing an immediate 100% startup crash for all worker instances. -
Failure Mode 2: Premature SQS Queue Message Deletion (Silent Data Loss) The agent relocates
sqs.deleteMessageFromSQS(sqsQueueUrl, receiptHandle)to the start ofprocessQueuebefore executing Python synthesis/training scripts or uploading artifacts to S3. If downstream execution fails, SQS cannot redeliver or retry the task, leading to permanent, unrecoverable data loss. -
Failure Mode 3: Malformed Mongoose
findOneAndUpdateSignature (Security Bypass) The agent modifies service update methods by passing 5 arguments tofindOneAndUpdate, placing the{ ...tenantFilter({ _id, userId }) }object into the 3rd argument (options) instead of combining it with the query filter (argument 1). Consequently, the query remains unscoped ({ _id: data._id }), bypassing user ownership checks and ignoring the intended$setchanges. -
Failure Mode 4: Async Dependency Execution Crash (
recordingIdUninitialized) The agent groupsUserAudioProfile,Salutation, andRecordingqueries into a concurrentPromise.allblock. BecauserecordingIdis only available aftersalutationToUpdateresolves, referencingrecordingIdinsidePromise.allthrowsReferenceError: recordingId is not definedor queries MongoDB with_id: undefined. -
Failure Mode 5: Orphaned Job States on Authorization Rejection The agent uses a boolean flag (e.g.,
authorized = false) and guards MongoDB status updates in thecatchblock withif (authorized). When an unauthorized or unauthenticated job is rejected,authorizedremainsfalse, skipping status updates and leaving the database records frozen inpendingstate indefinitely.
Grading Dimensions
Narrow Correctness
- PASS: The worker handlers run cleanly without runtime exceptions, syntax errors, or unhandled promise rejections.
- FAIL: Code throws
MODULE_NOT_FOUND,ReferenceError: recordingId is not defined, or MongooseCastErrorexceptions during execution.
Broader Correctness
- PASS: All primary and secondary MongoDB queries and updates enforce
userIdscoping, preventing cross-tenant access. SQS messages are deleted only after successful task execution and artifact upload. - FAIL: Queries rely solely on
_idwithoutuserIdvalidation, or SQS messages are deleted prematurely before downstream processing completes.
Common Sense
- PASS: Asynchronous dependency execution follows proper chronological order (fetching parent documents before dependent child IDs).
- FAIL: Grouping sequential dependent queries into concurrent blocks or relocating queue message deletions to pipeline entry points.
Verification & Thoroughness
- PASS: The worker pipeline behavior and database error transitions are verified against expected queue message schemas.
- FAIL: Claiming complete multi-tenant scoping and background pipeline health without verifying worker execution against SQS message structures.
Scoring Guide
- PASS (1.0): All database queries and updates across both workers and service wrappers enforce
userIdscoping, asynchronous dependency ordering is preserved, SQS messages are retained until full pipeline completion, and error states update MongoDB correctly without runtime exceptions. - FAIL (0.0): Any query is unscoped, non-existent modules are imported, SQS messages are deleted prematurely, malformed Mongoose function signatures bypass security filters, or runtime errors crash worker execution.