Skip to content

[PB-6470]: feature/encrypt and decrypt the attachments mail#60

Merged
xabg2 merged 5 commits into
masterfrom
feature/encrypt-attachment
Jun 9, 2026
Merged

[PB-6470]: feature/encrypt and decrypt the attachments mail#60
xabg2 merged 5 commits into
masterfrom
feature/encrypt-attachment

Conversation

@xabg2

@xabg2 xabg2 commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Upload the attachment encrypted with a session key (which is encrypted with the pub key of each of the recipients) and decrypt the attachment before download it by using the session key (which is decrypted with the privkey of the user recipient).

@xabg2 xabg2 requested a review from jzunigax2 June 8, 2026 09:51
@xabg2 xabg2 self-assigned this Jun 8, 2026
@xabg2 xabg2 added the enhancement New feature or request label Jun 8, 2026
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 8, 2026

Copy link
Copy Markdown

Deploying mail-web with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4013c68
Status: ✅  Deploy successful!
Preview URL: https://dc87990f.mail-web-ea0.pages.dev
Branch Preview URL: https://feature-encrypt-attachment.mail-web-ea0.pages.dev

View logs

@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 3fbe1924-c6d9-4b2f-98c9-57f242e053ee

📥 Commits

Reviewing files that changed from the base of the PR and between 56995b6 and 4013c68.

📒 Files selected for processing (1)
  • src/services/upload-manager/index.ts

📝 Walkthrough

Walkthrough

This PR implements encrypted attachment handling end-to-end: refactors compose-side hooks to manage per-session attachment encryption keys, introduces NetworkService for encrypted upload/download with retry logic, modernizes UploadManager to use session-scoped instances, extends mail decryption to expose envelope data for key recovery, and integrates encrypted downloads in the mail preview.

Changes

Encrypted attachments pipeline

Layer / File(s) Summary
Dependency updates and mail encryption contract extensions
package.json, src/services/mail-encryption/index.ts, src/services/mail-encryption/index.test.ts
SDK and internxt-crypto versions are bumped. MailEncryptionService.buildEncryptionBlock now accepts attachmentsSessionKey and returns wrapped attachment keys alongside body keys; new methods decryptAttachmentsSessionKey and encryptAttachment handle per-mail key recovery and symmetric file encryption. Tests updated to pass the attachments key across all encryption scenarios.
Encrypted network transfer service
src/services/network/index.ts, src/services/network/network.test.ts
New NetworkService provides encrypted upload() with transient error retry classification and download() with session-key-based decryption, both with cancellation hooks. Comprehensive tests cover success paths, retry/exhaustion, cancellation, and error propagation for both operations.
Upload manager queue orchestration
src/services/upload-manager/index.ts, src/services/upload-manager/upload-manager.test.ts
UploadManager refactored from singleton instance to constructor-scoped instances accepting sessionKey and callbacks. New public methods enqueue(id, file), retry(id), cancel(id), and clear() drive queue-backed uploads through NetworkService. Tests verify concurrency limits, callback wiring, cancellation, and retry behavior.
Decrypted mail envelope exposure and session key hook
src/hooks/mail/useDecryptedMail.ts, src/hooks/mail/useDecryptedMail.test.tsx, src/hooks/mail/useAttachmentsSessionKey.ts, src/hooks/mail/useAttachmentsSessionKey.test.tsx
useDecryptedMail now exposes envelope: EncryptionBlock | null from decryption. New useAttachmentsSessionKey(mailId, envelope) hook decrypts and caches per-mail attachment session keys, deferring until keypair is available and guarding against stale updates. Tests validate null checks, caching, deferred decryption, and error logging behavior.
Compose attachment session key generation and hook wiring
src/components/compose-message/index.tsx, src/components/compose-message/hooks/useAttachments.ts, src/components/compose-message/hooks/useAttachments.test.ts, src/components/compose-message/hooks/useComposeSend.ts, src/components/compose-message/hooks/useComposeSend.test.ts
ComposeMessageDialog generates a per-composition attachmentsSessionKey via useState. useAttachments(sessionKey) becomes session-scoped, storing file on each task and enqueueing through the new manager instance. useComposeSend accepts attachmentsSessionKey and passes it into buildEncryptionBlock. Tests updated to mock the new manager constructor, callbacks, and buildEncryptionBlock signature.
Mail preview envelope propagation and encrypted download integration
src/features/mail/MailView.tsx, src/features/mail/components/mail-preview/index.tsx, src/features/mail/components/mail-preview/preview/index.tsx
Decrypted envelope is threaded through MailViewPreviewMailPreview. Attachment download switches from MailService.downloadAttachment to NetworkService.download, using attachmentsSessionKey derived from useAttachmentsSessionKey(mailId, envelope). Filename resolution and error handling preserved.
Send email test payload update
src/services/sdk/mail/mail.service.test.ts
Encrypted email test payload now includes attachmentWrappedKeys field matching the updated MailEncryptionService.buildEncryptionBlock return contract.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Suggested reviewers

  • jzunigax2
  • CandelR
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding encryption and decryption support for mail attachments with session keys.
Description check ✅ Passed The description is directly related to the changeset, explaining the attachment encryption/decryption mechanism using session keys wrapped with recipient public keys.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/encrypt-attachment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Comment thread src/services/mail-encryption/index.ts Outdated
Comment on lines +199 to +212
/**
* Encrypt the session key for the attachments
* @param sessionKey - The session key to encrypt
* @param email - The email of the user to encrypt for
* @param userPubKey - The user public key of the user to encrypt for
* @returns - The hybrid ciphertext and encrypted key
*/
async encryptAttachmentSessionKey(sessionKey: Uint8Array<ArrayBufferLike>, email: string, userPubKey: string) {
const enc = await encryptKeysHybrid(sessionKey, {
email,
publicHybridKey: base64ToUint8Array(userPubKey),
});
return { hybridCiphertext: enc.hybridCiphertext, encryptedKey: enc.encryptedKey };
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is not called anywhere

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed. Good catch

@xabg2 xabg2 requested a review from jzunigax2 June 8, 2026 15:16

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/services/mail-encryption/index.test.ts (1)

169-176: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Update the parse fixture to match the current encryption envelope contract.

This fixture omits attachmentWrappedKeys, so the parse test does not validate the full envelope shape used by current encrypted attachments flow.

Proposed fix
     const block = {
       version: 'v1' as const,
       encryptedText: 'et',
       encryptedPreview: 'ep',
       wrappedKeys: [{ hybridCiphertext: 'h', encryptedKey: 'k' }],
+      attachmentWrappedKeys: [{ hybridCiphertext: 'ah', encryptedKey: 'ak' }],
     };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/mail-encryption/index.test.ts` around lines 169 - 176, The test
fixture for parseEncryptionBlock is missing the attachmentWrappedKeys field
required by the current envelope contract; update the expected `block` object in
the test (used with `ENCRYPTED_EMAIL_PREFIX` and parsed by
`mailEncryption.parseEncryptionBlock`) to include an `attachmentWrappedKeys`
property (e.g., an empty array or appropriate wrapped key entries) so the parsed
shape matches the full encryption envelope used by encrypted attachments.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/components/compose-message/hooks/useAttachments.test.ts`:
- Around line 44-58: Move the test-suite mock-restoration call into the setup
block: remove vi.restoreAllMocks() from afterEach and add vi.restoreAllMocks()
at the start of beforeEach (before any stubbing/resetting like vi.stubGlobal,
enqueue.mockReset, retryFn.mockReset, etc.) so mocks are restored before each
test is configured; keep vi.unstubAllGlobals() in afterEach if needed for global
cleanup.

In `@src/features/mail/components/mail-preview/preview/index.tsx`:
- Around line 44-55: The Preview component currently performs crypto key
derivation and async download side effects in its onDownload handler; extract
that logic into a new hook (e.g., usePreviewDownload) so Preview is render-only.
Create usePreviewDownload(mailId, envelope) that encapsulates
useAttachmentsSessionKey, any key derivation, and the async
NetworkService.instance.download orchestration, and returns a stable onDownload
callback plus any loading/error states and the attachmentsSessionKey if needed.
Replace the in-component onDownload and the useAttachmentsSessionKey call in
Preview with the hook's returned values and pass only render-ready
callbacks/data (sanitizedBody, attachments, subject, onDownload) into the
Preview component. Ensure the hook handles errors and side effects and that
Preview contains no async logic or crypto work.
- Around line 51-55: The call to NetworkService.instance.download currently
passes attachmentsSessionKey! which can be null and causes failures; add a
null-safe guard before invoking NetworkService.instance.download (inside the
preview component/function that performs the download) so that if
attachmentsSessionKey is null/undefined you skip or defer the download and
render a safe placeholder or retry logic instead of calling download with an
invalid value; only call NetworkService.instance.download with a validated
Uint8Array attachmentsSessionKey, and use the existing mailId and attachment
objects when the key is present.

In `@src/hooks/mail/useAttachmentsSessionKey.test.tsx`:
- Around line 23-29: The test setup resets mocks in afterEach but policy
requires restoring mocks at the start of each test; move vi.restoreAllMocks()
into the beforeEach block so it runs before
useMailKeysMock.mockReturnValue(KEYPAIR) (i.e., update the beforeEach containing
useMailKeysMock to first call vi.restoreAllMocks()), and remove
vi.restoreAllMocks() from afterEach, ensuring useMailKeysMock and other mocks
are reset before Arrange.

In `@src/services/mail-encryption/index.ts`:
- Around line 180-182: The decryptAttachmentsSessionKey method should validate
envelope.attachmentWrappedKeys before calling trialDecryptKey so malformed
envelopes raise an EnvelopeDecryptionError instead of a raw runtime error;
inside decryptAttachmentsSessionKey (the function shown) check that
envelope.attachmentWrappedKeys is present and is an array (and optionally
non-empty/contains expected entries), and if the check fails throw new
EnvelopeDecryptionError with a clear message, otherwise call and return
this.trialDecryptKey(envelope.attachmentWrappedKeys, keypair).

In `@src/services/network/index.ts`:
- Line 5: Replace the relative parent import for MailEncryptionService with the
repository path alias: update the import of MailEncryptionService (currently
"import { MailEncryptionService } from '../mail-encryption'") to use the
alias-based path (e.g. "`@/services/mail-encryption`") so internal modules under
src/ use the `@/`* alias; ensure the imported symbol name MailEncryptionService
remains unchanged.
- Line 51: The returned object currently sets name using "name ?? fileName",
which always selects the required input "name" and ignores a server-provided
canonical filename; change the fallback order so the server-provided "fileName"
is preferred when present (i.e., set the returned name to fileName ?? name) by
updating the return statement that currently returns { blob, name: name ??
fileName } to use the reversed fallback; keep the symbols blob, name, and
fileName intact.

In `@src/services/network/network.test.ts`:
- Around line 46-53: The test suite restores mocks in afterEach but policy
requires restoring before each test; update the setup so vi.restoreAllMocks() is
called at the start of the beforeEach block (before uploadAttachment.mockReset()
and encryptAttachment.mockClear()) to ensure a clean slate; locate the
beforeEach/afterEach in network.test.ts and move the restore call into
beforeEach (and remove it from afterEach) while keeping the
uploadAttachment.mockReset and encryptAttachment.mockClear calls after the
restore.
- Line 3: The import statement for NetworkService uses a relative path './index'
instead of the project's path alias. Replace the relative import path with the
appropriate `@/`* alias to align with the project's coding guidelines for internal
module imports in the NetworkService import statement.

In `@src/services/upload-manager/index.ts`:
- Around line 20-29: The UploadManager class in src/services breaks the service
singleton contract by requiring runtime constructor parameters; fix it by either
(A) turning UploadManager into a true singleton: make the constructor private,
add public static readonly instance = new UploadManager(), add an
init(sessionKey: Uint8Array, callbacks: UploadManagerCallbacks) method to set
session-scoped values (and update any code using new UploadManager(...) to call
UploadManager.instance.init(...)), and keep existing methods (process, q, jobs)
referencing the instance fields; or (B) move this class out of src/services into
a session-scoped module (e.g., src/lib or src/session) so it can remain
constructed per-session without violating the services contract — choose one
approach and update imports/usages accordingly (referencing class UploadManager,
constructor, process, jobs, q, and UploadManager.instance when applying option
A).
- Line 3: Replace the parent-relative import of NetworkService with the project
alias import pattern: update the import statement that currently imports
NetworkService (from '../network') to use the '`@/`...' alias (e.g., import {
NetworkService } from '`@/`...') so it conforms to the internal import rule for
src/**/*.{ts,tsx}; ensure the imported symbol name remains NetworkService and
that any exported path matches the network service module's alias entry.
- Around line 74-79: After a successful upload the job is not removed from the
jobs map causing stale state and allowing retry(id) for completed uploads;
update the success path in the upload handler to clear job.canceler (as in the
catch) and remove the job from this.jobs (e.g., this.jobs.delete(job.id)) before
calling this.callbacks.onSuccess(job.id, result.blobId) so completed entries are
not retained; keep the existing cancel/errored behavior unchanged.

In `@src/services/upload-manager/upload-manager.test.ts`:
- Line 2: Update the test import to use the repository internal-alias path
instead of a relative path: replace the current import of UploadManager and
UploadManagerCallbacks from './index' with the alias import that begins with
'`@/`...' so the file imports UploadManager and type UploadManagerCallbacks via
the internal alias (matching other src imports and repository conventions).
- Around line 26-32: Move the global mock restoration into the test setup by
calling vi.restoreAllMocks() inside the beforeEach and remove the
vi.restoreAllMocks() call from afterEach; specifically, update the beforeEach
block to call vi.restoreAllMocks() (then upload.mockReset() can run afterward)
and delete the afterEach block that currently calls vi.restoreAllMocks(),
referencing the existing beforeEach, afterEach, upload.mockReset, and
vi.restoreAllMocks symbols to locate the changes.

---

Outside diff comments:
In `@src/services/mail-encryption/index.test.ts`:
- Around line 169-176: The test fixture for parseEncryptionBlock is missing the
attachmentWrappedKeys field required by the current envelope contract; update
the expected `block` object in the test (used with `ENCRYPTED_EMAIL_PREFIX` and
parsed by `mailEncryption.parseEncryptionBlock`) to include an
`attachmentWrappedKeys` property (e.g., an empty array or appropriate wrapped
key entries) so the parsed shape matches the full encryption envelope used by
encrypted attachments.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 9032a5f9-f6c8-4b75-8a67-ba9a804ca7c1

📥 Commits

Reviewing files that changed from the base of the PR and between def5593 and 56995b6.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (21)
  • package.json
  • src/components/compose-message/hooks/useAttachments.test.ts
  • src/components/compose-message/hooks/useAttachments.ts
  • src/components/compose-message/hooks/useComposeSend.test.ts
  • src/components/compose-message/hooks/useComposeSend.ts
  • src/components/compose-message/index.tsx
  • src/features/mail/MailView.tsx
  • src/features/mail/components/mail-preview/index.tsx
  • src/features/mail/components/mail-preview/preview/index.tsx
  • src/hooks/mail/useAttachmentsSessionKey.test.tsx
  • src/hooks/mail/useAttachmentsSessionKey.ts
  • src/hooks/mail/useDecryptedMail.test.tsx
  • src/hooks/mail/useDecryptedMail.ts
  • src/services/mail-encryption/index.test.ts
  • src/services/mail-encryption/index.ts
  • src/services/network/index.ts
  • src/services/network/network.test.ts
  • src/services/sdk/mail/mail.service.test.ts
  • src/services/upload-manager/index.ts
  • src/services/upload-manager/upload-manager.test.ts
  • src/types/mail/upload-manager/index.ts
💤 Files with no reviewable changes (1)
  • src/types/mail/upload-manager/index.ts

Comment thread src/components/compose-message/hooks/useAttachments.test.ts
Comment on lines +44 to +55
const Preview = ({ mailId, subject, body, attachments, envelope }: PreviewProps) => {
const { translate } = useTranslationContext();
const sanitizedBody = purify.sanitize(body);
const attachmentsSessionKey = useAttachmentsSessionKey(mailId, envelope ?? null);

const onDownload = async (attachment: EmailAttachment) => {
try {
const { data, contentType } = await MailService.instance.downloadAttachment(
mailId,
attachment.blobId,
attachment.name,
attachment.type,
);
const blob = new Blob([data], { type: contentType || attachment.type });
const { blob, name } = await NetworkService.instance.download({
...attachment,
mailId: mailId,
attachmentsSessionKey: attachmentsSessionKey!,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

Move preview download orchestration into a hook, keep component render-only.

This component now owns crypto key derivation and async download side effects. Extract this into a use<...> hook and pass render-ready callbacks/data into the component. As per coding guidelines, “Components must be dumb; hooks should contain state/effects/event handlers.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/features/mail/components/mail-preview/preview/index.tsx` around lines 44
- 55, The Preview component currently performs crypto key derivation and async
download side effects in its onDownload handler; extract that logic into a new
hook (e.g., usePreviewDownload) so Preview is render-only. Create
usePreviewDownload(mailId, envelope) that encapsulates useAttachmentsSessionKey,
any key derivation, and the async NetworkService.instance.download
orchestration, and returns a stable onDownload callback plus any loading/error
states and the attachmentsSessionKey if needed. Replace the in-component
onDownload and the useAttachmentsSessionKey call in Preview with the hook's
returned values and pass only render-ready callbacks/data (sanitizedBody,
attachments, subject, onDownload) into the Preview component. Ensure the hook
handles errors and side effects and that Preview contains no async logic or
crypto work.

Source: Coding guidelines

Comment thread src/features/mail/components/mail-preview/preview/index.tsx
Comment thread src/hooks/mail/useAttachmentsSessionKey.test.tsx
Comment thread src/services/mail-encryption/index.ts
import type { UploadAttachmentResponse } from '@internxt/sdk/dist/mail/types';
import type { UploadAttachmentCallbacks, UploadAttachmentTask, UploadHandle } from '@/types/mail/upload-manager';
import type { RequestCanceler } from '@internxt/sdk/dist/shared/http/types';
import { NetworkService } from '../network';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use alias import for the internal network service.

Line 3 should import via @/* instead of a parent-relative path.

Proposed fix
-import { NetworkService } from '../network';
+import { NetworkService } from '`@/services/network`';

As per coding guidelines, src/**/*.{ts,tsx} requires internal imports to use the @/* alias.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/upload-manager/index.ts` at line 3, Replace the parent-relative
import of NetworkService with the project alias import pattern: update the
import statement that currently imports NetworkService (from '../network') to
use the '`@/`...' alias (e.g., import { NetworkService } from '`@/`...') so it
conforms to the internal import rule for src/**/*.{ts,tsx}; ensure the imported
symbol name remains NetworkService and that any exported path matches the
network service module's alias entry.

Source: Coding guidelines

Comment on lines +20 to 29
export class UploadManager {
private readonly jobs: Map<string, UploadJob> = new Map();
private readonly q: QueueObject<UploadJob>;

/**
* The retry method is used to restart an upload that has failed
* @param id - The ID of the upload task
* @param callbacks - The callbacks to call when the upload is complete (success or error)
* @returns - void
*/
retry(id: string, callbacks: UploadAttachmentCallbacks): void {
const existing = this.tasks.get(id);
if (!existing) return;
this.cancelTask(existing);
this.enqueueTask(id, existing.file, callbacks);
constructor(
private readonly sessionKey: Uint8Array,
private readonly callbacks: UploadManagerCallbacks,
) {
this.q = queue<UploadJob>(this.process, UPLOAD_CONCURRENCY);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | 🏗️ Heavy lift

UploadManager in src/services breaks the repo singleton service contract.

This service is constructed directly with runtime parameters and has no public static readonly instance. Either restore a singleton entrypoint or move this session-scoped orchestrator out of src/services to align with architecture constraints.

As per coding guidelines, services in src/services/**/*.ts must follow public static readonly instance = new ServiceName() and be consumed via ServiceName.instance.method().

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/upload-manager/index.ts` around lines 20 - 29, The UploadManager
class in src/services breaks the service singleton contract by requiring runtime
constructor parameters; fix it by either (A) turning UploadManager into a true
singleton: make the constructor private, add public static readonly instance =
new UploadManager(), add an init(sessionKey: Uint8Array, callbacks:
UploadManagerCallbacks) method to set session-scoped values (and update any code
using new UploadManager(...) to call UploadManager.instance.init(...)), and keep
existing methods (process, q, jobs) referencing the instance fields; or (B) move
this class out of src/services into a session-scoped module (e.g., src/lib or
src/session) so it can remain constructed per-session without violating the
services contract — choose one approach and update imports/usages accordingly
(referencing class UploadManager, constructor, process, jobs, q, and
UploadManager.instance when applying option A).

Source: Coding guidelines

Comment thread src/services/upload-manager/index.ts
import { MailService } from '@/services/sdk/mail';
import type { UploadAttachmentResponse } from '@internxt/sdk/dist/mail/types';
import { AxiosResponseError } from '@internxt/sdk/dist/shared/types/errors';
import { UploadManager, type UploadManagerCallbacks } from './index';

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use the internal alias import in this test file.

Line 2 should import through @/* to match repository import conventions.

Proposed fix
-import { UploadManager, type UploadManagerCallbacks } from './index';
+import { UploadManager, type UploadManagerCallbacks } from '`@/services/upload-manager`';

As per coding guidelines, all src/**/*.{ts,tsx} files must use @/* for internal imports.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { UploadManager, type UploadManagerCallbacks } from './index';
import { UploadManager, type UploadManagerCallbacks } from '`@/services/upload-manager`';
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/upload-manager/upload-manager.test.ts` at line 2, Update the
test import to use the repository internal-alias path instead of a relative
path: replace the current import of UploadManager and UploadManagerCallbacks
from './index' with the alias import that begins with '`@/`...' so the file
imports UploadManager and type UploadManagerCallbacks via the internal alias
(matching other src imports and repository conventions).

Source: Coding guidelines

Comment thread src/services/upload-manager/upload-manager.test.ts
@sonarqubecloud

sonarqubecloud Bot commented Jun 8, 2026

Copy link
Copy Markdown

@xabg2 xabg2 merged commit 86f1a91 into master Jun 9, 2026
6 checks passed
@xabg2 xabg2 deleted the feature/encrypt-attachment branch June 9, 2026 07:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants