{"_id":"@axosolaman/secure-next-upload","name":"@axosolaman/secure-next-upload","dist-tags":{"latest":"1.1.0"},"versions":{"1.1.0":{"name":"@axosolaman/secure-next-upload","version":"1.1.0","description":"Production-grade, zero-server-bandwidth secure multi-entity file and media upload system with 5-layer security verification for Next.js and modern web apps.","main":"./dist/index.js","module":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","require":"./dist/index.js"},"./server":{"types":"./dist/server/index.d.ts","import":"./dist/server/index.mjs","require":"./dist/server/index.js"},"./client":{"types":"./dist/client/index.d.ts","import":"./dist/client/index.mjs","require":"./dist/client/index.js"},"./config":{"types":"./dist/config/index.d.ts","import":"./dist/config/index.mjs","require":"./dist/config/index.js"}},"scripts":{"build":"tsup","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"keywords":["secure-next-upload","axosolaman","axo-security","security-researcher","file-upload","avatar-upload","cwe-434","magic-bytes","s3","cloudflare-r2","presigned-url","zero-bandwidth","exif-stripper","nextjs","react","drizzle","prisma"],"author":{"name":"axosolaman","url":"https://github.com/axosolaman"},"repository":{"type":"git","url":"git+https://github.com/axosecurity/secure-next-upload.git"},"homepage":"https://github.com/axosecurity/secure-next-upload#readme","bugs":{"url":"https://github.com/axosecurity/secure-next-upload/issues"},"license":"MIT","peerDependencies":{"next":"^14.0.0 || ^15.0.0","react":"^18.0.0 || ^19.0.0","react-dom":"^18.0.0 || ^19.0.0"},"dependencies":{"@aws-sdk/client-s3":"^3.600.0","@aws-sdk/s3-request-presigner":"^3.600.0","browser-image-compression":"^2.0.2","sonner":"^1.5.0","zod":"^3.23.0"},"devDependencies":{"@types/node":"^20.0.0","@types/react":"^18.0.0 || ^19.0.0","@types/react-dom":"^18.0.0 || ^19.0.0","next":"^14.2.0","react":"^18.3.0","react-dom":"^18.3.0","tsup":"^8.5.1","typescript":"^5.4.0"},"gitHead":"c9c5b2f29b6e953c0d1a682b977dc9b21253dddc","_id":"@axosolaman/secure-next-upload@1.1.0","_nodeVersion":"25.8.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-aFlOYZ5HqmuM/sboFWoSJV7i6PoPy+6cC1N7c+3eGfLy+gTms4nKVhmioXBpApsN/l7MZTgN221/dC+hyPsprQ==","shasum":"aa1680c31cd521848130aca9483cacc74b8d9bea","tarball":"https://registry.npmjs.org/@axosolaman/secure-next-upload/-/secure-next-upload-1.1.0.tgz","fileCount":37,"unpackedSize":538897,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCYyEXuM9ioBTIq4C8svTsRnvsF4Sfwmrcl96QiHSNpYwIhAM6NlnNij2K9kgpwThZQslnmNkd3P7NJsd7b1Rib7023"}]},"_npmUser":{"name":"axosolaman","email":"sjsojib722@gmail.com"},"directories":{},"maintainers":[{"name":"axosolaman","email":"sjsojib722@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/secure-next-upload_1.1.0_1786843030202_0.5454517476736"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-16T01:17:10.060Z","1.1.0":"2026-08-16T01:17:10.355Z","modified":"2026-08-16T01:17:10.607Z"},"maintainers":[{"name":"axosolaman","email":"sjsojib722@gmail.com"}],"description":"Production-grade, zero-server-bandwidth secure multi-entity file and media upload system with 5-layer security verification for Next.js and modern web apps.","homepage":"https://github.com/axosecurity/secure-next-upload#readme","keywords":["secure-next-upload","axosolaman","axo-security","security-researcher","file-upload","avatar-upload","cwe-434","magic-bytes","s3","cloudflare-r2","presigned-url","zero-bandwidth","exif-stripper","nextjs","react","drizzle","prisma"],"repository":{"type":"git","url":"git+https://github.com/axosecurity/secure-next-upload.git"},"author":{"name":"axosolaman","url":"https://github.com/axosolaman"},"bugs":{"url":"https://github.com/axosecurity/secure-next-upload/issues"},"license":"MIT","readme":"# 🚀 Secure Next Upload (`@axosolaman/secure-next-upload`)\n\n[![npm version](https://img.shields.io/npm/v/@axosolaman/secure-next-upload.svg)](https://www.npmjs.com/package/@axosolaman/secure-next-upload)\n[![Security Researcher: axosolaman](https://img.shields.io/badge/Security%20Researcher-axosolaman-blue.svg)](https://github.com/axosolaman)\n[![Research: Axo Security](https://img.shields.io/badge/Research-Axo%20Security-purple.svg)](https://github.com/axosecurity)\n[![CWE-434 Mitigated](https://img.shields.io/badge/CWE--434-Immune-brightgreen.svg)]()\n[![Zero Server Bandwidth](https://img.shields.io/badge/Bandwidth-0%20Server%20Load-brightgreen.svg)]()\n[![Bug Bounty Hardened](https://img.shields.io/badge/Bug%20Bounty-Hardened-orange.svg)]()\n[![TypeScript](https://img.shields.io/badge/TypeScript-100%25-blue.svg)]()\n[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)\n\n> **The definitive high-performance, zero-server-bandwidth secure file and media upload engine for Next.js, React, and modern web architectures.**  \n> Built by security researchers to systematically eliminate the **#1 highest-paying vulnerability classes** (CWE-434, CWE-22, CWE-200, Stored XSS) while saving companies thousands in cloud bandwidth, server RAM crashes, and storage bills.\n\n---\n\n## ⚡ Why Secure Next Upload?\n\nTraditional file upload architectures stream massive binary payloads directly through your backend API servers. This saturates bandwidth, crashes serverless runtimes (e.g. Vercel 4.5MB payload limits), inflates hosting bills, and exposes applications to malicious webshell uploads.\n\n**Secure Next Upload delivers a modern, frictionless architecture:**\n\n* **⚡ Zero Server Bandwidth**: Uploads stream directly from the browser to Cloudflare R2 / AWS S3 via cryptographic Presigned PUT URLs. Your web servers never touch, buffer, or proxy the binary files.\n* **🚀 3x–5x Faster Parallel Uploads**: Upload multi-file batches simultaneously using a built-in asynchronous worker pool (`concurrency: 3–5`) with per-file progress tracking and fault-tolerant completion.\n* **🎨 Client-Side Web Worker Optimization**: Automatically compresses 15MB mobile photos to ~800KB web-optimized images and strips high-precision GPS/EXIF metadata in browser background threads *before* uploading.\n* **🛡️ Military-Grade 5-Layer Security**: Pre-flight validation, presigned token locks, S3 `HeadObject` verification, 16-byte binary magic byte inspection, and single-use intent state machines.\n* **🧩 Drop-in React Components & Headless Hook**: Includes sleek, fully accessible UI components (`FileDropzone`, `AvatarUploader`, `DocumentUploader`, `UploadProgress`) and a headless `useFileUpload` hook.\n* **🗄️ Database Agnostic**: Includes production-ready schemas for both **Prisma** and **Drizzle ORM**.\n\n---\n\n## 🛡️ Security at a Glance: Vulnerabilities Secure Next Upload Neutralizes\n\nFile upload endpoints are historically the most exploited attack surface on bug bounty platforms (**HackerOne, Bugcrowd, Intigriti**). Secure Next Upload provides defense-in-depth immunity against the most severe vulnerability classes:\n\n* 💥 **CWE-434 (Unrestricted File Upload / Webshell RCE)** ➔ **Neutralized** by server-side 16-byte binary magic byte inspection (`0x89PNG`, `%PDF`, `FF D8 FF`, `RIFF...WEBP`), strict MIME whitelisting, and cloud-edge content locks.\n* 📍 **CWE-200 / CWE-359 (EXIF & GPS Geolocation Leakage)** ➔ **Neutralized** by in-memory browser Web Worker stripping before upload, protecting user privacy and preventing GDPR/HIPAA compliance fines.\n* 🛑 **CWE-22 / CWE-646 (Path Traversal & Filename Tampering)** ➔ **Neutralized** by generating unpredictable 7-character randomized object keys (`avatars/xK9_m2Q.webp`), completely discarding untrusted user filenames and path sequences.\n* 💣 **CWE-400 (Denial of Service & Serverless RAM Exhaustion)** ➔ **Neutralized** by routing binary streams directly to cloud storage, completely bypassing Node.js/Next.js memory buffers.\n* 🦠 **CWE-79 (Stored Cross-Site Scripting via SVG/HTML)** ➔ **Neutralized** by strict MIME isolation and sandboxed delivery.\n\n```\n┌─────────────────────────────────────────────────────────────────────────────────────────────┐\n│ 🔬 Deep Security & Threat Model Research                                                    │\n│                                                                                             │\n│ For the complete Master CWE Mitigation Matrix, bug bounty payout data ($3k-$30k+ RCEs),    │\n│ and why server-side EXIF stripping creates RCE/SSRF/DoS (CVE-2021-22204 / ImageTragick):    │\n│                                                                                             │\n│ 👉 Read the Full Defensive Security & Threat Model in SECURITY.md ───────────────►         │\n└─────────────────────────────────────────────────────────────────────────────────────────────┘\n```\n\n👉 **[Read the Complete Defensive Security & Threat Model in SECURITY.md →](./SECURITY.md)**\n\n---\n\n## 💼 Immense Business & Financial Impact\n\n| Impact Metric | Traditional Server Uploads | Secure Next Upload |\n| :--- | :--- | :--- |\n| **Server Bandwidth & RAM** | ❌ High (Full file payload streams through server) | ✅ **0 KB Server Load** (Direct-to-Cloud PUT) |\n| **Multi-File Upload Speed** | ⏱️ Sequential (30–45s for 10 files) | ⚡ **Parallel Pool (7–9s for 10 files)** |\n| **Cloud Storage Costs** | 💸 Uncompressed 15MB images fill buckets | 📉 **70%+ Savings** (Compressed in Web Worker) |\n| **Serverless Execution Limits** | 💥 Crashes on Vercel/Lambda (4.5MB limit) | ✅ **Unlimited File Sizes Supported** |\n| **Security Breach Risk** | 🚨 Critical (CWE-434 RCE webshell payouts) | 🛡️ **Hardened 5-Layer Verification** |\n\n---\n\n## 📊 Deep Comparison: Secure Next Upload vs. Alternatives\n\n### 1. Open Source Ecosystem Packages\n\n| Project | Similarity | Key Strengths | Missing / Weaker Compared to Secure Next Upload | Best For |\n| :--- | :--- | :--- | :--- | :--- |\n| **`@axosolaman/secure-next-upload`** | ⭐️ **Current** | **Zero Server Bandwidth**, 5-layer security verification, 16-byte magic byte check, Web Worker EXIF stripping, parallel concurrency pool (`concurrency: 3-5`), atomic replacement, multi-entity registry. | None — complete end-to-end production architecture. | **Production apps wanting maximum security, speed & $0 cloud markup.** |\n| **`next-upload`** *(TimMikeladze)* | **High** | Presigned URLs, Next.js focused, optional DB metadata, S3/R2/MinIO support. | Weaker security (no deep 16-byte magic byte inspection, no multi-entity registry, no client-side Web Worker EXIF/compression). | Simple Next.js apps needing basic presigned uploads. |\n| **`vs3`** | **High** | Type-safe, presigned uploads, magic-byte detection, React hooks, Next.js handlers, Zod schemas. | Less opinionated multi-entity registry, no built-in atomic asset replace (`swapMode: \"atomic_replace\"`), or 5-layer pipeline. | Developers wanting basic type safety + single-file validation. |\n| **`octoload`** | **Medium-High** | Direct-to-S3/R2, CLI for schema generation, Drizzle integration, TypeScript-first. | Image-focused, lacks comprehensive 5-layer security pipeline and client-side EXIF/compression. | Teams using Drizzle wanting CLI-generated code. |\n| **`@circulo-ai/upload`** | **Medium** | Multi-provider (S3, Azure Blob), presigned + multipart, path traversal protection. | No deep binary magic byte inspection, no client-side Web Worker image optimization. | Multi-cloud projects needing Azure + S3 coverage. |\n\n---\n\n### 2. Managed SaaS Services & Client Libraries\n\n| Service / Architecture | Category | Pros | Cons vs. Secure Next Upload |\n| :--- | :--- | :--- | :--- |\n| **`UploadThing`** | Managed SaaS + SDK | Extremely easy setup for Next.js, type-safe route handler, good developer experience. | ❌ You don't own the underlying storage infrastructure, monthly recurring subscription fees, less defensive binary inspection layers. |\n| **`Vercel Blob`** | Managed Cloud Storage | Native Vercel integration, simple presigned upload workflow. | ❌ Vendor lock-in to Vercel ecosystem, proprietary bandwidth pricing, less advanced binary security verification. |\n| **`Uppy + S3 Companion`** | Client UI Library | Highly customizable UI dashboard, resumable tus/multipart uploads, multi-source file picking. | ❌ Client-only library. You must still build, maintain, and secure the backend validation and database intent pipeline yourself. |\n| **`DIY Raw S3 Presigned URLs`** | Custom In-House Code | Complete custom architectural freedom. | ❌ Massive engineering burden. You must build rate limiting, 5-layer security, magic-byte checking, EXIF stripping, and orphan garbage collection from scratch. |\n\n---\n\n### ⚠️ What Vulnerabilities & Risks Do Alternatives Create?\n\nIf you build with or rely on traditional alternatives, your application remains exposed to specific architectural attack vectors:\n\n| Alternative Architecture / Pattern | Vulnerabilities & Security Risks Introduced | Real-World Impact on Your App |\n| :--- | :--- | :--- |\n| **Traditional Server Buffering (`Multer`, `Busboy`, raw API routes)** | **CWE-400 (Denial of Service / OOM Crashes)**<br>• Full binary payload buffers into server memory.<br>• Serverless functions (Vercel / AWS Lambda) crash instantly on 4.5MB limit.<br>• Heavy server CPU spikes and bandwidth saturation. | 💥 **Server Outages & Wasted Bandwidth**<br>Thousands in bloated cloud bills; memory crashes during concurrent traffic spikes. |\n| **Basic Presigned URLs (`next-upload`, DIY S3 scripts)** | **CWE-434 & CWE-646 (MIME & Extension Spoofing)**<br>• Lacks deep 16-byte binary magic byte inspection.<br>• Blindly trusts client-provided `Content-Type` headers.<br>• Polyglot webshells (`shell.php.png`) pass through to cloud storage. | 🚨 **Remote Code Execution (RCE) / Malware Hosting**<br>Attackers host phishing pages or executable malware directly on your CDN domain. |\n| **Server-Side EXIF Processing (`ExifTool`, `ImageMagick`)** | **Command Injection / SSRF / Memory Corruption**<br>• Backend server invokes CLI parsers on untrusted binary inputs.<br>• Exposes infrastructure to **CVE-2021-22204 (GitLab RCE)** and ImageTragick. | 💀 **Critical Server Takeover (CVSS 10.0)**<br>Attackers execute arbitrary shell commands inside your server environment. |\n| **Unstripped Raw Uploads (No Client Web Worker Stripping)** | **CWE-200 / CWE-359 (EXIF Geolocation Leakage)**<br>• Uploads unstripped camera photos to public storage buckets.<br>• Leaks precise GPS latitude/longitude, home addresses, device serials. | ⚖️ **User Doxxing & GDPR/HIPAA Fines**<br>Massive regulatory privacy violation penalties and permanent user trust destruction. |\n| **Client-Only Libraries without Intent States (`Uppy` alone)** | **CWE-20 & CWE-862 (Missing Authorization & Replay)**<br>• Relies solely on frontend JavaScript checks (easily bypassed with curl/Burp).<br>• No atomic single-use confirmation state machines. | 🔓 **Unauthorized Asset Overwrite & Race Conditions**<br>Attackers overwrite other users' files or upload unauthorized payloads. |\n| **No Atomic Replacement (`swapMode: \"append\"` only)** | **Storage Bloat & Dead Orphan Accumulation**<br>• Updating an avatar leaves old files orphaned indefinitely on S3.<br>• Failed/abandoned presigned URLs accumulate unverified storage bills. | 💸 **Exponential Cloud Storage Billing**<br>Paying for thousands of gigabytes of dead, unlinked zombie files. |\n\n---\n\n## 💡 Real-World Use Cases\n\n1. **User Profile & Avatar Management**:\n   * Circular avatar uploader with client-side cropping and automatic atomic deletion of old avatars from storage (`swapMode: \"atomic_replace\"`).\n2. **E-Commerce & Photo Galleries**:\n   * Drag-and-drop batch uploader that compresses 15MB mobile photos to ~800KB web-optimized images in Web Workers and uploads 10–20 files in parallel.\n3. **Documents & Invoice Vaults**:\n   * Strict PDF, DOCX, XLSX, and TXT upload verification with magic-byte checking and per-document download/removal actions.\n4. **Chat & Ticket Attachments**:\n   * Headless `useFileUpload` hook for seamless custom file inputs with individual and aggregate progress bars.\n\n---\n\n## 📦 Installation\n\n```bash\n# Using npm\nnpm install @axosolaman/secure-next-upload @aws-sdk/client-s3 @aws-sdk/s3-request-presigner browser-image-compression zod sonner\n\n# Using pnpm\npnpm add @axosolaman/secure-next-upload @aws-sdk/client-s3 @aws-sdk/s3-request-presigner browser-image-compression zod sonner\n```\n\n---\n\n## 🚀 3-Minute Quick Start\n\n### 1. Configure Environment Variables (`.env.local`)\n\n```env\n# Cloudflare R2 / AWS S3 Credentials\nR2_ACCOUNT_ID=your_cloudflare_account_id\nR2_ACCESS_KEY_ID=your_access_key_id\nR2_SECRET_ACCESS_KEY=your_secret_access_key\nR2_BUCKET_NAME=your_bucket_name\nR2_PUBLIC_URL=https://pub-your-id.r2.dev\n\n# Database Connection\nDATABASE_URL=\"postgresql://user:password@localhost:5432/mydb\"\n```\n\n---\n\n### 2. Define Upload Rules (`src/config/uploader.ts`)\n\n```typescript\nimport { defineUploadRegistry } from \"@axosolaman/secure-next-upload/config\";\n\nexport const uploadRegistry = defineUploadRegistry({\n  avatar: {\n    folder: \"avatars\",\n    allowedMimes: [\"image/jpeg\", \"image/png\", \"image/webp\"],\n    maxSizeBytes: 5 * 1024 * 1024, // 5MB\n    magicByteCheck: true,\n    compressClientSide: true,\n    compressionOptions: { maxSizeMB: 1.5, maxWidthOrHeight: 1024 },\n    swapMode: \"atomic_replace\", // Deletes previous avatar automatically\n    requiresAuth: true,\n  },\n  document: {\n    folder: \"documents\",\n    allowedMimes: [\"application/pdf\", \"text/plain\", \"application/zip\"],\n    maxSizeBytes: 50 * 1024 * 1024, // 50MB\n    magicByteCheck: true,\n    compressClientSide: false,\n    swapMode: \"append\",\n    requiresAuth: true,\n  },\n  gallery: {\n    folder: \"gallery\",\n    allowedMimes: [\"image/jpeg\", \"image/png\", \"image/webp\"],\n    maxSizeBytes: 20 * 1024 * 1024,\n    magicByteCheck: true,\n    compressClientSide: true,\n    compressionOptions: { maxSizeMB: 4, maxWidthOrHeight: 2560 },\n    swapMode: \"append\",\n    requiresAuth: true,\n  },\n});\n```\n\n---\n\n### 3. Create Next.js API Routes (App Router)\n\n#### `src/app/api/upload/request/route.ts`\n```typescript\nimport { createUploadRequestHandler } from \"@axosolaman/secure-next-upload/server\";\nimport { uploadRegistry } from \"@/config/uploader\";\nimport { db } from \"@/db\";\n\nexport const POST = createUploadRequestHandler({\n  registry: uploadRegistry,\n  getAuthUser: async (req) => {\n    // Return authenticated user or null\n    return { id: \"user_123\", authId: \"user_123\" };\n  },\n  db: {\n    getUser: async (authId) => ({ id: authId }),\n    createIntent: async (data) => db.uploadIntent.create({ data }),\n    getIntent: async (id, userId) => db.uploadIntent.findFirst({ where: { id } }),\n    updateIntentStatus: async (id, status, completedAt) => {\n      await db.uploadIntent.update({ where: { id }, data: { status, completedAt } });\n    },\n  },\n});\n```\n\n#### `src/app/api/upload/confirm/route.ts`\n```typescript\nimport { createUploadConfirmHandler } from \"@axosolaman/secure-next-upload/server\";\nimport { uploadRegistry } from \"@/config/uploader\";\nimport { db } from \"@/db\";\n\nexport const POST = createUploadConfirmHandler({\n  registry: uploadRegistry,\n  db: {\n    getUser: async (authId) => ({ id: authId }),\n    createIntent: async (data) => db.uploadIntent.create({ data }),\n    getIntent: async (id, userId) => db.uploadIntent.findFirst({ where: { id } }),\n    updateIntentStatus: async (id, status, completedAt) => {\n      await db.uploadIntent.update({ where: { id }, data: { status, completedAt } });\n    },\n  },\n});\n```\n\n---\n\n## 🎨 Frontend Usage & React Components\n\n### 1. Headless Hook `useFileUpload` (Single & Parallel Uploads)\n\n```tsx\n\"use client\";\n\nimport { useFileUpload } from \"@axosolaman/secure-next-upload/client\";\n\nexport function GalleryUpload() {\n  const {\n    uploadMultiple,\n    isUploading,\n    progress,\n    status,\n    fileItems,\n    error,\n  } = useFileUpload({\n    entityType: \"gallery\",\n    concurrency: 4, // Upload up to 4 files simultaneously\n    onFileSuccess: (res, file) => console.log(`✓ Uploaded ${file.name}:`, res.fileUrl),\n    onFileError: (err, file) => console.error(`✗ Failed ${file.name}:`, err.message),\n  });\n\n  return (\n    <div>\n      <input\n        type=\"file\"\n        multiple\n        onChange={(e) => e.target.files && uploadMultiple(Array.from(e.target.files))}\n      />\n\n      {isUploading && (\n        <div className=\"mt-4\">\n          <p>Overall Progress: {progress}% ({status})</p>\n          {fileItems.map((item) => (\n            <div key={item.id}>\n              {item.file.name}: {item.status} ({item.progress}%)\n            </div>\n          ))}\n        </div>\n      )}\n      {error && <p className=\"text-red-500\">{error}</p>}\n    </div>\n  );\n}\n```\n\n---\n\n### 2. Multi-File Cloud Dropzone\n\n```tsx\nimport { FileDropzone } from \"@axosolaman/secure-next-upload/client\";\n\nexport function GallerySection() {\n  return (\n    <FileDropzone\n      entityType=\"gallery\"\n      multiple={true}\n      maxFiles={10}\n      label=\"Drop gallery photos here\"\n      sublabel=\"PNG, JPEG, WebP (Compressed in Web Worker)\"\n      onSuccess={(results) => console.log(\"Uploaded batch:\", results)}\n    />\n  );\n}\n```\n\n---\n\n### 3. Circular Avatar Uploader\n\n```tsx\nimport { AvatarUploader } from \"@axosolaman/secure-next-upload/client\";\n\nexport function ProfileHeader({ user }) {\n  return (\n    <AvatarUploader\n      entityType=\"avatar\"\n      currentAvatarUrl={user.avatarUrl}\n      onAvatarUpdate={async (newUrl) => {\n        await updateUserAvatar(user.id, newUrl);\n      }}\n    />\n  );\n}\n```\n\n---\n\n### 4. Document & Attachment Vault\n\n```tsx\nimport { DocumentUploader } from \"@axosolaman/secure-next-upload/client\";\n\nexport function AttachmentsList() {\n  return (\n    <DocumentUploader\n      entityType=\"document\"\n      onUploadSuccess={(doc) => console.log(\"Attached document:\", doc)}\n      onRemoveDocument={(id) => console.log(\"Removed document:\", id)}\n    />\n  );\n}\n```\n\n---\n\n## 🗄️ Database Schemas\n\n### Drizzle ORM (`schema.ts`)\n```typescript\nimport { pgTable, uuid, varchar, integer, timestamp, jsonb, index } from \"drizzle-orm/pg-core\";\n\nexport const uploadIntents = pgTable(\"upload_intents\", {\n  id: uuid(\"id\").defaultRandom().primaryKey(),\n  userId: uuid(\"user_id\"),\n  entityType: varchar(\"entity_type\", { length: 50 }).default(\"general\").notNull(),\n  objectKey: varchar(\"object_key\", { length: 512 }).notNull().unique(),\n  originalFileName: varchar(\"original_file_name\", { length: 255 }).notNull(),\n  mimeType: varchar(\"mime_type\", { length: 100 }).notNull(),\n  fileSize: integer(\"file_size\").notNull(),\n  status: varchar(\"status\", { length: 20 }).default(\"pending\").notNull(), // pending | completed | failed | expired\n  metadata: jsonb(\"metadata\"),\n  presignedUrlExpiresAt: timestamp(\"presigned_url_expires_at\").notNull(),\n  createdAt: timestamp(\"created_at\").defaultNow().notNull(),\n  completedAt: timestamp(\"completed_at\"),\n}, (table) => ({\n  userStatusIdx: index(\"upload_intents_user_status_idx\").on(table.userId, table.status),\n  entityStatusIdx: index(\"upload_intents_entity_status_idx\").on(table.entityType, table.status),\n}));\n```\n\n### Prisma ORM (`schema.prisma`)\n```prisma\nmodel UploadIntent {\n  id                    String    @id @default(uuid())\n  userId                String?   @map(\"user_id\")\n  entityType            String    @default(\"general\") @map(\"entity_type\")\n  objectKey             String    @unique @map(\"object_key\")\n  originalFileName      String    @map(\"original_file_name\")\n  mimeType              String    @map(\"mime_type\")\n  fileSize              Int       @map(\"file_size\")\n  status                String    @default(\"pending\")\n  metadata              Json?\n  presignedUrlExpiresAt DateTime  @map(\"presigned_url_expires_at\")\n  createdAt             DateTime  @default(now()) @map(\"created_at\")\n  completedAt           DateTime? @map(\"completed_at\")\n\n  @@index([userId, status])\n  @@index([entityType, status])\n  @@map(\"upload_intents\")\n}\n```\n\n---\n\n## 🌐 Storage Bucket CORS Configuration\n\nAdd this CORS configuration to your Cloudflare R2 or AWS S3 bucket:\n\n```json\n[\n  {\n    \"AllowedOrigins\": [\n      \"http://localhost:3000\",\n      \"https://yourdomain.com\"\n    ],\n    \"AllowedMethods\": [\n      \"GET\",\n      \"PUT\",\n      \"HEAD\"\n    ],\n    \"AllowedHeaders\": [\n      \"Content-Type\",\n      \"Content-Length\"\n    ],\n    \"ExposeHeaders\": [\n      \"ETag\",\n      \"Content-Length\"\n    ],\n    \"MaxAgeSeconds\": 3600\n  }\n]\n```\n\n---\n\n## 👨‍💻 Author & Security Researcher Profile\n\n**Secure Next Upload** (`@axosolaman/secure-next-upload`) is created, architected, and maintained by **[axosolaman](https://github.com/axosolaman)** ([Axo Security](https://github.com/axosecurity)).\n\n* **Lead Security Researcher**: **[axosolaman](https://github.com/axosolaman)**\n* **GitHub Profile**: [@axosolaman](https://github.com/axosolaman)\n* **Organization**: [Axo Security (@axosecurity)](https://github.com/axosecurity)\n* **Core Expertise**: Web Application Security, Bug Bounty Research, Threat Modeling, Zero-Trust Cloud Architectures, and Defensive AppSec Engineering.\n\n> 💬 **Feedback & Security Audits**: If you are using `@axosecurity/secure-next-upload` in your production stack, feel free to star the repo or connect directly on GitHub with **[axosolaman](https://github.com/axosolaman)**.\n\n---\n\n## 📄 License\n\nMIT License © 2026 axosolaman (Axo Security). Open source for commercial and enterprise production use.\n","readmeFilename":"README.md","_rev":"1-bdb8a0047eab4e0d6a7502f069889a47"}