Skip to content

Dev#105

Merged
CodeMeAPixel merged 15 commits into
masterfrom
dev
Jun 13, 2026
Merged

Dev#105
CodeMeAPixel merged 15 commits into
masterfrom
dev

Conversation

@CodeMeAPixel

@CodeMeAPixel CodeMeAPixel commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Summary by CodeRabbit

  • Security Improvements

    • Hardened input validation (SSRF/ReDoS mitigation) and added repo security artifacts and license scan badge.
  • Performance

    • File uploads no longer block on malware scans (background scanning); storage provider and cache persist across reloads for faster operations.
  • Removals

    • External status page integration removed; status display converted to a static link.
  • Bug Fixes

    • Pagination display fixed; assorted type/validation and sitemap fixes; improved integration test error responses.

@coderabbitai

coderabbitai Bot commented Jun 13, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@NodeByteLTD, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 9 minutes and 35 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bfe30404-fa43-4095-a75e-81e1886b584a

📥 Commits

Reviewing files that changed from the base of the PR and between 0843168 and d42d704.

📒 Files selected for processing (20)
  • .github/README.md
  • CHANGELOG.md
  • app/(main)/[userUrlId]/[filename]/page.tsx
  • app/(main)/auth/alpha-migration/page.tsx
  • app/(main)/blog/[slug]/page.tsx
  • app/(main)/blog/page.tsx
  • app/(main)/dashboard/bucket/page.tsx
  • app/(main)/dashboard/client.tsx
  • app/(main)/dashboard/squads/client.tsx
  • app/api/admin/integrations/test/route.ts
  • app/api/files/route.ts
  • app/api/settings/route.ts
  • packages/components/theme/theme-initializer.tsx
  • packages/lib/cache/session-cache.ts
  • packages/lib/files/filename.ts
  • packages/lib/storage/quota.ts
  • packages/types/react-jsx-compat.d.ts
  • proxy.ts
  • scripts/hash-file-passwords.mjs
  • scripts/migrate-config.mjs

Walkthrough

This release removes the Kener external status integration, optimizes file uploads with asynchronous VirusTotal scanning, threads emailVerified through the auth system, persists storage/Stripe caches across hot-reloads, hardens integration test input validation, and fixes pagination.

Changes

Kener Status Page Integration Removal

Layer / File(s) Summary
Kener module stub and status API endpoint
packages/lib/kener/index.ts, app/api/status/route.ts
Kener client logic replaced with a stub comment; /api/status now returns 404 immediately instead of fetching aggregated status.
StatusIndicator static link and footer cleanup
packages/components/layout/StatusIndicator.tsx, packages/components/layout/footer.tsx
StatusIndicator rewritten from a stateful fetch component into a static emerald-dot link; removed from footer's responsive wrapper.
Remove Kener from config schema and integration testing
packages/lib/config/index.ts, app/api/settings/route.ts, app/api/admin/integrations/test/route.ts
Kener integration definition removed from configSchema/DEFAULT_CONFIG, secret masking, and integration test routing.
Documentation and release notes
.github/README.md, CHANGELOG.md, package.json
CHANGELOG documents removal and security/performance items; README badges/acknowledgment text adjusted; package version bumped to 2.4.6.

File Upload Async VirusTotal & Optimization

Layer / File(s) Summary
Local vs. async security validation split
packages/lib/files/security-validation.ts
New validateFileSecurityChecks for synchronous extension/MIME/ZIP-bomb checks; new scanWithVirusTotal for async background detection; deprecated combined function now wraps both.
Batch file expiration lookup helper
packages/lib/events/handlers/file-expiry.ts
New getFileExpirationInfoBatch fetches expiration dates for multiple files in a single event query instead of per-file calls.
Upload flow: concurrent buffering, preloaded auth, background scanning
app/api/files/route.ts
Pre-load emailVerified/role data, buffer file and resolve storage provider/filename concurrently, compute fileSizeMB early, hash password before DB transaction, upload buffered bytes, create DB record using fileSizeMB, and trigger async VirusTotal with quarantine on detection; listing endpoints use batched expiration lookups.

Auth System: emailVerified Field

Layer / File(s) Summary
AuthenticatedUser type and session cache schema
packages/lib/auth/api-auth.ts, packages/lib/cache/session-cache.ts
Add emailVerified: boolean to both AuthenticatedUser and CachedUserSession interfaces and persist in session cache writes.
Populate emailVerified across all auth paths
packages/lib/auth/api-auth.ts
Thread emailVerified from cached sessions, ORM lookups, API keys, and upload tokens.
Upload validation with preloaded auth data
packages/lib/files/upload-validation.ts
validateEmailVerified and validateUploadRequest accept optional preloaded emailVerified/role to skip redundant DB queries.

Storage Provider & Stripe Sync Cache Persistence

Layer / File(s) Summary
Storage provider globalThis caching
packages/lib/storage/index.ts
Cache initialized storage provider on globalThis.__storageProvider so it survives Next.js hot-reloads; invalidate clears both module and global values.
Stripe sync TTL cache globalThis migration
packages/lib/storage/quota.ts
Move per-user Stripe sync cache from module-local Map to typed globalThis.__stripeSyncCache for hot-reload persistence.

Integration Test Input Validation & Error Handling

Layer / File(s) Summary
Stripe and Resend error handling improvements
app/api/admin/integrations/test/route.ts
Add clearer auth-failure branching (401/403 handling) and structured error detail responses.
Cloudflare, Discord, GitHub input sanitization and validation
app/api/admin/integrations/test/route.ts
Add sanitizeCloudflareAccountId/sanitizeDiscordServerId to validate integration credentials before API calls; improve Discord webhook validation with HTTPS/host/pathname checks; refactor GitHub error mapping to distinguish 401 vs 404.
Vultr and SMTP error handling
app/api/admin/integrations/test/route.ts
Refactor Vultr test with structured auth/error handling and optional account email in success message; adjust SMTP to return specific failure message and detail.

Minor Fixes & Cleanups

Layer / File(s) Summary
Pagination pageCount fix and filename hyphen trimming
packages/components/dashboard/user-list.tsx, packages/lib/files/filename.ts
Update user-list pagination to use pageCount; refactor filename hyphen trimming from regex to explicit index scanning.
Logging format and URL normalization cleanup
app/api/settings/route.ts, packages/lib/storage/index.ts, packages/lib/storage/sync-buckets.ts, packages/lib/utils/index.ts
Update sync-buckets logging to use object spread and structured error fields; refactor URL trailing-slash removal to a manual trim loop; adjust settings/storage logging formatting.
Version bump and changelog documentation
package.json, CHANGELOG.md
Version bumped to 2.4.6; CHANGELOG documents security hardening, status page removal, scanning automation, performance improvements, and fixes.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.37% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Dev' is vague and generic, providing no meaningful information about the changeset's primary changes. Consider using a more descriptive title that highlights the main change, such as 'Remove Kener status page integration and add security hardening for v2.4.6' or similar.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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 packages/lib/config/index.ts Fixed
Comment thread app/api/settings/route.ts Fixed
Comment thread packages/lib/storage/quota.ts Fixed
Comment thread packages/lib/storage/quota.ts Fixed
CodeMeAPixel and others added 6 commits June 13, 2026 09:44
…tion or class'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…tion or class'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…ble types'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
…tion or class'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 11

Caution

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

⚠️ Outside diff range comments (1)
app/api/files/route.ts (1)

55-73: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Fix emailVerified shape before assigning squad owner to authenticated user.

This is the compile blocker from CI (TS2322 around Line 72). Prisma returns emailVerified as Date | null, but this flow expects a boolean contract. Convert it when building the acting user object (and when passing preloaded values).

💡 Suggested fix
-      const ownerUser = await prisma.user.findUnique({
+      const ownerUserRaw = await prisma.user.findUnique({
         where: { id: squad.ownerUserId },
         select: {
           id: true,
           email: true,
           name: true,
           storageUsed: true,
           storageQuotaMB: true,
           urlId: true,
           role: true,
           randomizeFileUrls: true,
           preferredUploadDomain: true,
           emailVerified: true,
         },
       })
-      if (!ownerUser)
+      if (!ownerUserRaw)
         return apiError('Squad owner not found', HTTP_STATUS.UNAUTHORIZED)
-      user = ownerUser
+      user = {
+        ...ownerUserRaw,
+        emailVerified: Boolean(ownerUserRaw.emailVerified),
+      }

@@
-      { emailVerified: user.emailVerified, role: user.role }
+      { emailVerified: Boolean(user.emailVerified), role: user.role }

Also applies to: 169-174

🤖 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 `@app/api/files/route.ts` around lines 55 - 73, Prisma's
ownerUser.emailVerified is Date|null but the code expects a boolean; when
building the acting user set user = ownerUser, convert emailVerified to a
boolean (e.g., !!ownerUser.emailVerified or Boolean(ownerUser.emailVerified)) so
the user object matches the expected shape, and apply the same conversion to any
other preload/assignment sites that pass emailVerified (the other occurrence
noted around the later preloaded values) so all usages (prisma.user.findUnique
result, assigned user variable, and any preloadedValue assignments) store a
boolean rather than a Date|null.

Source: Pipeline failures

🤖 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 @.github/README.md:
- Line 5: The README still mentions "Kener" in the feature/stack sections;
remove or update those references to reflect the new status-page approach by
replacing any "Kener" text/links with the new status-page wording or removing
the stale bullet, and update any related badges/links so the feature/stack
entries and examples reference the status-page integration instead of Kener
(search for "Kener" in the README to locate and change each occurrence).

In `@app/api/admin/integrations/test/route.ts`:
- Around line 61-63: Several provider fetches (e.g., the Stripe call that uses
secretKey and the other provider fetches) lack a timeout and can hang; add the
same AbortController timeout pattern used elsewhere: create an AbortController,
start a setTimeout that calls controller.abort() after the desired timeout, and
pass { signal: controller.signal, headers: { ... } } into each fetch options
object (replace plain fetch calls that only set headers). Use the same timeout
duration and clear the timer after the response is received; ensure any existing
variable names like secretKey are preserved and only the fetch options and
timeout wiring are changed.

In `@app/api/files/route.ts`:
- Around line 124-125: The code converts uploadedFile.size to MB via bytesToMB
for quota checks but then persists that MB value into byte-based fields,
corrupting accounting; revert storage writes to bytes: use the original
uploadedFile.size (or convert MB back to bytes with MB * 1024 * 1024 if you only
have the MB value) when assigning file.size and when incrementing storageUsed,
and only use bytesToMB(uploadedFile.size) for validation/display logic
(references: bytesToMB, uploadedFile.size, file.size, storageUsed).
- Around line 275-289: The quarantine branch inside the scanWithVirusTotal
callback currently calls Promise.allSettled([...]) and ignores the results;
update this to await the Promise.allSettled result, inspect each outcome for a
rejected status from storageProvider!.deleteFile(filePath) or
prisma.file.update({ where: { id: fileRecord.id }, ... }), and handle failures
explicitly (e.g., log error with fileId and vtResult, surface or rethrow if
critical, and optionally retry or mark a quarantine-failure flag in the DB).
Ensure the handler preserves the original quarantine behavior on success but
does not silently swallow failures from Promise.allSettled.

In `@CHANGELOG.md`:
- Around line 27-29: The changelog entry inaccurately states the `/api/status`
route was removed; update the wording in the release notes to reflect the
current state by saying the dynamic status integration was removed and the
`/api/status` route remains present but now returns a 404 NOT_FOUND (rather than
being deleted), and indicate that StatusIndicator now links statically to
emberlystat.us and no longer performs external API calls; ensure the terms
`/api/status` and `StatusIndicator` are used so readers can locate the affected
behavior.

In `@packages/components/layout/StatusIndicator.tsx`:
- Around line 13-14: The StatusIndicator component currently renders a static
green dot and the text "System Status" which implies live healthy state; update
the JSX in StatusIndicator to use a neutral indicator and wording since it's
just a link: change the span's className from "bg-emerald-500" to a neutral
color like "bg-gray-400" (or a neutral token used in your design system) and
change the adjacent label text from "System Status" to "View System Status"
(also update any aria-label/title to match) so the UI no longer implies a live
health check.

In `@packages/lib/cache/session-cache.ts`:
- Line 42: When hydrating cached sessions replace the direct cast "return
JSON.parse(data) as CachedUserSession" with code that parses the JSON into a
temporary object, ensures the emailVerified property exists and is coerced to a
boolean (e.g., set obj.emailVerified = Boolean(obj.emailVerified) or default to
false if missing), then return the object typed as CachedUserSession;
specifically target the JSON.parse(...) expression and the CachedUserSession
result so older Redis entries missing emailVerified are backfilled on read.

In `@packages/lib/config/index.ts`:
- Around line 166-237: The config allows passthrough of unknown integration keys
so legacy fields like integrations.kener can survive safeParse/deepMerge and be
returned to ADMIN; update the fix by either: (A) tightening the configSchema for
integrations to remove unknown keys (remove .passthrough() on the integrations
object and provider sub-objects in configSchema) so unknown providers are
dropped during parse; or (B) explicitly strip legacy/unknown keys in
maskSecretsForAdmin() (add logic to remove integrations.kener and/or filter
integrations to a whitelist of known providers) so ADMIN responses never include
stale kener data; ensure changes touch the integrations schema in
config/index.ts (the integrations object and its provider sub-objects) and the
maskSecretsForAdmin() function used by app/api/settings/route.ts so the leak is
closed.

In `@packages/lib/files/filename.ts`:
- Around line 98-103: The sanitized slug (urlSafeName) can become empty after
replacing/trimming, so after the slice(s, e) in the slug creation block check if
urlSafeName === '' and if so assign a safe fallback (e.g. 'file' or 'untitled'
or 'file-' + a short random/hash) before it is used further; update the variable
urlSafeName in that same block (where baseNameWithoutExt and urlSafeName are
used) so downstream path construction that appends the extension never receives
an empty string.

In `@packages/lib/storage/quota.ts`:
- Around line 255-266: The code incorrectly treats a deliberate zero admin
override as "unset" because it uses falsy checks; change both checks that read
if (!baseQuotaMB) (and the subsequent if (!baseQuotaMB && defaultQuotaMB)) to
null/undefined checks so 0 is honored—e.g. use if (baseQuotaMB == null) (or if
(baseQuotaMB === undefined || baseQuotaMB === null)) when deciding to compute
plan-based quota, and use if (baseQuotaMB == null && defaultQuotaMB != null)
when falling back to defaultQuotaMB; keep the existing arithmetic using
planLimits.storageQuotaGB and perkStorageBonusGB unchanged.
- Around line 99-103: After performing the one-time Stripe sync (the block using
stripeSyncCache and STRIPE_SYNC_TTL_MS) do not simply return the most-recent
active subscription; re-apply the existing "storage-bucket-*" precedence logic
before returning limits. Concretely: when determining latestActiveSubscription
after the sync, prefer any active subscription whose product/type startsWith
"storage-bucket-" (and treat it with the bucket/unlimited semantics the original
precedence expects) over other active subscriptions, so you don't accidentally
return capped limits when a storage-bucket subscription exists; update the
selection logic that currently picks the newest active subscription to check for
and prefer storage-bucket-* subscriptions first.

---

Outside diff comments:
In `@app/api/files/route.ts`:
- Around line 55-73: Prisma's ownerUser.emailVerified is Date|null but the code
expects a boolean; when building the acting user set user = ownerUser, convert
emailVerified to a boolean (e.g., !!ownerUser.emailVerified or
Boolean(ownerUser.emailVerified)) so the user object matches the expected shape,
and apply the same conversion to any other preload/assignment sites that pass
emailVerified (the other occurrence noted around the later preloaded values) so
all usages (prisma.user.findUnique result, assigned user variable, and any
preloadedValue assignments) store a boolean rather than a Date|null.
🪄 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: CHILL

Plan: Pro

Run ID: aa365595-4dd3-495e-a667-6d8b113d7cef

📥 Commits

Reviewing files that changed from the base of the PR and between b2153d7 and eac3b92.

📒 Files selected for processing (23)
  • .github/README.md
  • CHANGELOG.md
  • app/api/admin/integrations/test/route.ts
  • app/api/files/route.ts
  • app/api/settings/route.ts
  • app/api/status/route.ts
  • package.json
  • packages/components/admin/settings/settings-manager.tsx
  • packages/components/dashboard/user-list.tsx
  • packages/components/layout/StatusIndicator.tsx
  • packages/components/layout/footer.tsx
  • packages/lib/auth/api-auth.ts
  • packages/lib/cache/session-cache.ts
  • packages/lib/config/index.ts
  • packages/lib/events/handlers/file-expiry.ts
  • packages/lib/files/filename.ts
  • packages/lib/files/security-validation.ts
  • packages/lib/files/upload-validation.ts
  • packages/lib/kener/index.ts
  • packages/lib/storage/index.ts
  • packages/lib/storage/quota.ts
  • packages/lib/storage/sync-buckets.ts
  • packages/lib/utils/index.ts
💤 Files with no reviewable changes (1)
  • packages/components/layout/footer.tsx

Comment thread .github/README.md
Comment thread app/api/admin/integrations/test/route.ts
Comment thread app/api/files/route.ts
Comment thread app/api/files/route.ts
Comment thread CHANGELOG.md
Comment thread packages/lib/cache/session-cache.ts Outdated
Comment thread packages/lib/config/index.ts
Comment thread packages/lib/files/filename.ts
Comment thread packages/lib/storage/quota.ts
Comment thread packages/lib/storage/quota.ts
Comment thread packages/lib/storage/quota.ts Fixed
CodeMeAPixel and others added 2 commits June 13, 2026 10:31
…ble types'

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
@CodeMeAPixel CodeMeAPixel merged commit eb59d45 into master Jun 13, 2026
12 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jun 13, 2026
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant