diff --git a/.env.template b/.env.template
index 706ee1a..18365ab 100644
--- a/.env.template
+++ b/.env.template
@@ -30,10 +30,6 @@ REDIS_URL="redis://default:password@localhost:6379"
# VirusTotal API Configuration
VIRUSTOTAL_API_KEY="your_virustotal_api_key"
-# Vultr Object Storage — used for automated S3 bucket provisioning
-# Generate at: https://my.vultr.com/settings/#settingsapi
-VULTR_API_KEY="your_vultr_api_key"
-
# Sentry Configuration
# DSN from: https://sentry.io → Project → Settings → Client Keys
NEXT_PUBLIC_SENTRY_DSN="https://xxxx@oXXXX.ingest.sentry.io/XXXX"
diff --git a/.github/README.md b/.github/README.md
deleted file mode 100644
index 5cd40ac..0000000
--- a/.github/README.md
+++ /dev/null
@@ -1,188 +0,0 @@
-# Emberly
-
-Emberly is an open source platform for modern file storage, sharing, and identity verification. Build your digital presence with powerful tools for teams and individuals.
-
-[](https://github.com/EmberlyOSS/Emberly/actions/workflows/build.yml) [](https://github.com/EmberlyOSS/Emberly/actions/workflows/codeql.yml)  [](https://app.fossa.com/projects/git%2Bgithub.com%2FEmberlyOSS%2FEmberly?ref=badge_shield&issueType=security)
-
-## Features
-
-**File Storage & Sharing**
-
-- S3 compatible object storage with configurable upload limits
-- Secure file sharing with customizable access controls
-- Real world file organization and management
-- Bandwidth efficient delivery through global infrastructure
-
-**Domain & Branding**
-
-- Custom domain support with annual registration
-- Personal or team branded file sharing pages
-- Domain SSL certificate management
-- DNS configuration assistance
-
-**Identity & Verification**
-
-- User verification badges with multiple tier options
-- Verification queue with application review system
-- Badge display on public profiles
-- Organization verification for teams
-
-**Team & Collaboration**
-
-- Squad based team subscriptions with seat based pricing
-- Granular permission management (roles: SUPPORT, DEVELOPER, MODERATOR, DESIGNER, STAFF)
-- Team member invitations and management
-- Shared storage pools with usage tracking
-
-**Applications & Trust**
-
-- Staff application system for organizational partnerships
-- Partner program enrollment
-- Verification badge applications
-- Ban appeal process with review workflow
-- Email notifications for all application updates
-
-**Administrative Tools**
-
-- Promo code management with configurable discounts
-- User management dashboard
-- Application review queue with multi stage triage
-- Service status page link ([emberlystat.us](https://emberlystat.us))
-- Analytics and usage reporting
-
-## Quick Start
-
-For development setup, contribution guidelines, and detailed documentation, see [CONTRIBUTING.md](CONTRIBUTING.md).
-
-### Prerequisites
-
-- Node.js 18+ or later
-- Bun package manager
-- PostgreSQL 14+ database
-- Redis 6+ (optional for caching)
-
-### Development Setup
-
-```bash
-# Clone the repository
-git clone https://github.com/EmberlyOSS/Emberly.git
-cd Emberly
-
-# Install dependencies
-bun install
-
-# Configure environment
-cp .env.template .env
-# Edit .env with your configuration
-
-# Initialize database
-bun prisma generate
-bun prisma migrate deploy
-
-# Start development server
-bun dev
-```
-
-The application will be available at http://localhost:3000.
-
-## Tech Stack
-
-**Frontend & Framework**
-
-- [Next.js 15](https://nextjs.org/) - React framework with App Router
-- [React 19](https://react.dev/) - UI library
-- [TypeScript](https://www.typescriptlang.org/) - Type safety
-- [Tailwind CSS](https://tailwindcss.com/) - Utility first styling
-- [shadcn/ui](https://ui.shadcn.com/) - Component library
-
-**Backend & Database**
-
-- [PostgreSQL](https://www.postgresql.org/) - Relational database
-- [Prisma ORM](https://www.prisma.io/) - Database toolkit
-- [Stripe](https://stripe.com/) - Payment processing
-- [Resend](https://resend.com/) - Email delivery
-
-**Infrastructure & Services**
-
-- [S3 compatible storage](https://aws.amazon.com/s3/) - File storage
-- [Next.js Auth](https://next-auth.js.org/) - Authentication
-- [Sentry](https://sentry.io/) - Error tracking
-
-**Development Tools**
-
-- [Bun](https://bun.sh/) - Runtime and package manager
-- [ESLint](https://eslint.org/) - Code linting
-- [Prisma Migrate](https://www.prisma.io/docs/orm/prisma-migrate) - Database migrations
-
-## Project Structure
-
-```
-app/ # Next.js App Router pages and routes
- (main)/ # Public user pages
- (raw)/ # Raw file serving
- (shorturl)/ # Short URL redirects
- api/ # API endpoints
-
-packages/
- components/ # React components
- - admin/ # Admin dashboard components
- - pricing/ # Pricing and plans
- - auth/ # Authentication UI
- - dashboard/ # User dashboard
- - ui/ # Base UI building blocks
-
- hooks/ # Custom React hooks
- - use file upload # File uploading
- - use profile # User profile data
- - use user content # User content queries
-
- lib/ # Utility functions
- - api/ # API helpers
- - auth/ # Authentication utilities
- - cache/ # Caching logic
- - stripe/ # Stripe integration
-
- types/ # TypeScript definitions
-
-prisma/ # Database schema and migrations
- - schema.prisma # Prisma schema definition
- - migrations/ # Migration files
-
-public/ # Static assets
-scripts/ # Build and utility scripts
-```
-
-## Contributing
-
-We welcome contributions from the community. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines including:
-
-- Development environment setup
-- Code standards and conventions
-- Pull request process
-- Commit message format
-- How to report issues
-- Community channels and support
-
-## Support
-
-Get help and connect with the community:
-
-- **Discord** - [Join our server](https://discord.gg/36spBmzZVB) for realtime discussions
-- **GitHub Discussions** - Ask questions and share ideas
-- **Email** - Contact [hey@embrly.ca](mailto:hey@embrly.ca) for support
-
-## License
-
-This project is licensed under the GNU Affero General Public License v3 (AGPL-3.0). See the [LICENSE](LICENSE) file for details.
-
-## Code of Conduct
-
-This project adheres to the Contributor Covenant Code of Conduct. By participating, you agree to uphold this code. See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for the full text.
-
-## Acknowledgments
-
-Thank you to all [contributors](https://github.com/EmberlyOSS/Emberly/graphs/contributors) who have helped make Emberly possible. We also appreciate the [open source projects and communities](https://github.com/EmberlyOSS/Emberly/network/dependencies) that make Emberly possible.
-
-
-
-
diff --git a/.gitignore b/.gitignore
index 99204e9..fe36055 100644
--- a/.gitignore
+++ b/.gitignore
@@ -64,8 +64,6 @@ next-env.d.ts
.idea/
.vscode/
.cursor/
-CLAUDE.md
-AGENTS.md
*.swp
*.swo
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000..7283800
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,323 @@
+# AGENTS.md — Emberly Codebase Guide for AI Agents
+
+This file is for AI coding assistants (Claude Code, GitHub Copilot, Cursor, etc.). It provides the practical context needed to work effectively in this codebase without re-deriving it every session.
+
+---
+
+## Project at a glance
+
+**Emberly** is an open-source file storage, sharing, discovery, and identity-verification platform.
+Stack: **Next.js 16 App Router · TypeScript (strict) · PostgreSQL (Prisma) · Redis · S3-compatible storage · Tailwind CSS · shadcn/ui**
+License: AGPL-3.0-only
+
+---
+
+## Essential commands
+
+```bash
+# Install
+bun install
+
+# Dev server (Turbopack)
+bun dev # http://localhost:3000
+
+# Type check (no emit)
+bun typecheck # tsc --noEmit
+
+# Lint / format
+bun lint
+bun lint:fix
+bun format # Prettier across all .ts/.tsx/.json/.md
+
+# Build
+bun run build
+
+# Database
+bun run db:generate # Regenerate Prisma client after schema changes
+bun run db:migrate # Create + apply a dev migration
+bun run db:deploy # Apply migrations (production/CI)
+bun run db:push # Push schema without a migration (prototyping only)
+bun run db:studio # GUI at http://localhost:5555
+bun run db:seed # Seed subscription plans
+```
+
+Run `bun typecheck` and `bun lint` before committing. Both run in CI.
+
+---
+
+## Directory map
+
+```
+app/ Next.js App Router
+ (main)/ UI pages (auth, admin, [userUrlId] file serving)
+ (raw)/ Raw file responses
+ (shorturl)/ Short-URL redirect handler
+ api/ ~180 REST endpoints (admin/, auth/, files/, users/, urls/, ...)
+
+packages/
+ components/ React component library
+ ui/ shadcn/ui base components
+ admin/ Admin UI
+ dashboard/ User dashboard
+ auth/ Auth UI
+ file/ File management UI
+ theme/ Snowfall / effects / dark mode
+ providers/ Context providers
+ shared/ Cross-cutting UI helpers
+ hooks/ Custom React hooks (use-file-upload, use-profile, ...)
+ lib/ Business logic
+ api/handler.ts Middleware wrapper for all API routes (auth, logging, error)
+ auth/ NextAuth config + helpers
+ events/ Event system (emitter · consumer · worker · handlers/)
+ database/ Prisma client singleton
+ cache/ Redis helpers
+ storage/ S3 / Vultr integration
+ emails/ Resend email templates
+ stripe/ Payment processing
+ permissions/ RBAC permission helpers
+ nexium/ Team/squad system
+ security/ Security utilities
+ logger/ Pino structured logging
+ startup/index.ts Server initialization (event system, Sentry, monitoring)
+ types/ Shared TypeScript definitions
+ events.ts Discriminated-union event types
+ dto/ Data-transfer object types
+
+prisma/
+ schema.prisma Source of truth for DB models
+ migrations/ Migration history (do not edit manually)
+ generated/ Generated Prisma client (do not edit)
+
+scripts/ One-off utilities (seed, media-kit, migration helpers)
+public/ Static assets
+.github/ CI workflows, CONTRIBUTING.md
+```
+
+---
+
+## API route conventions
+
+Every API handler must go through the wrapper in [packages/lib/api/handler.ts](packages/lib/api/handler.ts). It handles:
+
+- Request-ID tagging
+- Structured logging (Pino)
+- Session/auth validation
+- Standardized error responses
+
+**Never** write raw `NextResponse` handlers — always use the handler wrapper.
+
+```typescript
+// Correct pattern
+import { createHandler } from '@/lib/api/handler'
+
+export const GET = createHandler(async (req, ctx) => {
+ // ctx.session is populated if the handler requires auth
+})
+```
+
+---
+
+## Event system
+
+Background work goes through the event system in [packages/lib/events/](packages/lib/events/).
+
+- **Emit**: `packages/lib/events/emitter.ts` — publishes a typed event to the DB
+- **Handle**: `packages/lib/events/handlers/` — one file per domain (auth, file, email, billing, discord, audit, …)
+- **Worker**: runs when `EMBERLY_RUN_EVENT_WORKER=true`; processes queued events asynchronously
+
+Add new handlers in `handlers/` and register them in the consumer. Event types are in [packages/types/events.ts](packages/types/events.ts) — extend the discriminated union there first.
+
+---
+
+## Path aliases
+
+Configured in `tsconfig.json`. Use these everywhere; never use `../../..` relative paths across package boundaries.
+
+| Alias | Resolves to |
+| ---------------- | ----------------------- |
+| `@/*` | project root |
+| `@/components/*` | `packages/components/*` |
+| `@/lib/*` | `packages/lib/*` |
+| `@/hooks/*` | `packages/hooks/*` |
+| `@/types/*` | `packages/types/*` |
+| `@/database/*` | `prisma/*` |
+
+---
+
+## Code style rules
+
+- **TypeScript strict mode** — no implicit `any`. Use `unknown` + type narrowing instead.
+- **No `any`** — ESLint enforces this. The only allowed escape hatch is an explicit disable comment with a reason.
+- **Server components by default** — only add `'use client'` when hooks, events, or browser APIs are required.
+- **Functional components only** — hooks for state and side-effects.
+- **Tailwind for styling** — no inline styles, no CSS modules. Dark mode is implemented via Tailwind's `dark:` variant.
+- **shadcn/ui base components** — extend from `packages/components/ui/`, do not fork the components themselves.
+- **No comments explaining what the code does** — only add a comment when the _why_ is non-obvious (hidden constraint, workaround, invariant).
+
+### Naming
+
+| Thing | Convention |
+| --------------------- | ---------------------- |
+| Files | `kebab-case.tsx` |
+| React components | `PascalCase` |
+| Functions / variables | `camelCase` |
+| Constants | `SCREAMING_SNAKE_CASE` |
+| Types / interfaces | `PascalCase` |
+
+### Import order (enforced by Prettier plugin)
+
+1. React
+2. Next.js
+3. Third-party packages
+4. `@/components/…`
+5. `@/lib/…`
+6. `@/hooks/…`
+7. `@/types/…`
+8. Relative imports
+
+---
+
+## Commit convention (enforced by commitlint + Husky)
+
+```
+():
+```
+
+Types: `feat` · `fix` · `docs` · `style` · `refactor` · `perf` · `test` · `chore` · `ci` · `revert`
+
+Examples:
+
+```
+feat(auth): add magic-link sign-in flow
+fix(upload): resolve off-by-one in chunked upload progress
+refactor(api): consolidate 404 error path in handler wrapper
+```
+
+Commits that don't match the pattern are rejected by the pre-commit hook.
+
+---
+
+## Database rules
+
+- **Never** edit `prisma/migrations/` by hand.
+- **Never** call `db push` in production — use `db deploy`.
+- After any change to `schema.prisma`, run `bun run db:generate` to regenerate the client.
+- The Prisma client singleton lives in `packages/lib/database/` — always import from there, never instantiate `PrismaClient` directly.
+- Keep the generated client out of git (`prisma/generated/` is gitignored). CI regenerates it.
+
+---
+
+## Authentication
+
+- NextAuth v4 is configured in `packages/lib/auth/`.
+- Providers: Discord OAuth, GitHub OAuth, credentials (email + password).
+- Sessions are validated server-side via the API handler wrapper — do not roll your own session checks.
+- 2FA (TOTP) and magic links are supported; see `packages/lib/auth/` for helpers.
+- Password hashing: bcryptjs. Never store or log plaintext passwords.
+
+---
+
+## Permissions / RBAC
+
+Roles: `USER` · `STAFF` · `SUPPORT` · `DEVELOPER` · `MODERATOR` · `DESIGNER` · `PARTNER`
+
+Permission checks live in `packages/lib/permissions/`. Always use the helpers there; do not hardcode role string comparisons in route handlers.
+
+---
+
+## Storage
+
+Files are stored in S3-compatible object storage (AWS S3 or Vultr Object Storage). Metadata lives in the database; content lives in the bucket.
+
+- Client: `@aws-sdk/client-s3` — configured in `packages/lib/storage/`
+- Use pre-signed URLs for uploads/downloads; never proxy raw file bytes through the Next.js process unless absolutely necessary
+- Per-user bucket overrides are supported alongside the global default bucket
+
+---
+
+## Caching (Redis)
+
+Redis is used for:
+
+- Rate limiting
+- Session caching
+- Event handler state
+
+Helpers are in `packages/lib/cache/`. Import from there; do not create raw Redis clients.
+
+Redis is optional for local development but required in production.
+
+---
+
+## Environment variables
+
+Copy `.env.template` → `.env` to get started. Critical variables:
+
+| Variable | Purpose |
+| --------------------------------------- | ---------------------------------- |
+| `DATABASE_URL` | PostgreSQL connection string |
+| `REDIS_URL` | Redis connection string |
+| `NEXTAUTH_SECRET` | Session signing key (≥32 chars) |
+| `NEXTAUTH_URL` / `NEXT_PUBLIC_BASE_URL` | App base URL |
+| `DISCORD_OAUTH_CLIENT_ID/SECRET` | Discord OAuth |
+| `GITHUB_OAUTH_CLIENT_ID/SECRET` | GitHub OAuth |
+| `VIRUSTOTAL_API_KEY` | Malware scanning for uploads |
+| `VULTR_API_KEY` | S3 bucket provisioning |
+| `NEXT_PUBLIC_SENTRY_DSN` | Client-side error tracking |
+| `EMBERLY_RUN_CLOUD` | Enable cloud/marketing features |
+| `EMBERLY_RUN_EVENT_WORKER` | Enable background event processing |
+
+Never commit `.env`. Never log env vars. `SENTRY_AUTH_TOKEN` is build-time only (CI).
+
+---
+
+## CI pipelines
+
+| Workflow | Trigger | What it checks |
+| ------------- | -------------------------- | -------------------------------------------- |
+| `build.yml` | push/PR → master, PR → dev | install → prisma generate → migrate → build |
+| `quality.yml` | push/PR → master, PR → dev | install → prisma generate → typecheck → lint |
+| `codeql.yml` | push → master + weekly | CodeQL advanced security scan |
+
+Both `build` and `quality` use Node.js 22 + Bun + a PostgreSQL 16 service container.
+
+---
+
+## Security-sensitive areas
+
+- `packages/lib/security/` — rate limiting, IP checks, bot detection
+- `packages/lib/middleware/` — `auth-checker.ts`, `bot-handler.ts`
+- All file uploads go through VirusTotal scanning before acceptance
+- User-generated HTML is sanitized with DomPurify before rendering
+- Never introduce `dangerouslySetInnerHTML` without sanitization
+- SQL queries always go through Prisma — no raw SQL string interpolation
+- JWT/session tokens must never appear in logs or error responses
+
+---
+
+## Key third-party integrations
+
+| Service | Package | Location |
+| -------------- | ----------------------- | -------------------------------------- |
+| PostgreSQL | `@prisma/client` | `packages/lib/database/` |
+| Redis | `redis` | `packages/lib/cache/` |
+| S3 / Vultr | `@aws-sdk/client-s3` | `packages/lib/storage/` |
+| Email | `resend` | `packages/lib/emails/` |
+| Payments | `stripe` | `packages/lib/stripe/` |
+| Error tracking | `@sentry/nextjs` | `instrumentation.ts`, `next.config.ts` |
+| Logging | `pino` | `packages/lib/logger/` |
+| OCR | `tesseract.js` | `packages/lib/ocr/` |
+| Code editor | `@uiw/react-codemirror` | used in file preview components |
+
+---
+
+## What to avoid
+
+- Do not bypass the API handler wrapper — missing auth/logging is a security hole.
+- Do not call `new PrismaClient()` — use the singleton.
+- Do not use `any` without a disable comment and a reason.
+- Do not add `'use client'` to components that don't need it — it expands the client bundle.
+- Do not commit secrets, `.env`, or `prisma/generated/`.
+- Do not write raw SQL strings — Prisma only.
+- Do not add feature flags, backwards-compat shims, or half-finished stubs — implement fully or don't implement.
+- Do not add error handling for scenarios that can't happen — trust Prisma/Next.js guarantees at internal boundaries.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6d9e23f..6c766ef 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,35 @@ All notable changes to this project will be documented in this file.
The format is based on "Keep a Changelog" and follows [Semantic Versioning](https://semver.org/).
+## [2.4.7] - 2026-06-15
+
+### Added
+
+- **Core Pool Storage Buckets** — `StorageBucket` now supports `isCore` (boolean) and `priority` (integer) fields. Core buckets are shared across all users via least-filled load balancing (`fileCount ASC, priority DESC`). Dedicated buckets are assigned per-user or per-squad. Priority breaks ties when two core buckets have equal file counts — higher number wins. Default is `0` (no preference).
+- **`File → StorageBucket` relation** — Files now track which bucket they were stored in via `storageBucketId`. This is used at serve time to route reads, streams, deletes, OCR, and thumbnail generation to the correct bucket rather than the global default.
+- **User bucket assignment UI** — New `UserBucketAssignment` component in the admin settings Storage tab. Paginated user list with per-user bucket dropdown and save button. Clears assignment (falls back to core pool) or assigns a dedicated bucket; triggers credentials email on assignment.
+- **Admin storage bucket manager — `isCore` / `priority` UI** — Edit dialog now includes a Core Pool Bucket toggle and a Priority number input (visible when `isCore` is on). List rows show Core Pool badge (violet), Dedicated badge, file count, and priority for core buckets.
+- **Bucket connection test — per-bucket provider** — `POST /api/admin/storage/buckets/[id]/test` now uses an explicit `select` in `findUnique` (fixes a `@prisma/adapter-pg` driver adapter issue that caused `findUnique` without a select to return `null` for existing records). Test error detail is now surfaced inline in the UI alongside the status message.
+- **`PUT /api/admin/storage/buckets` — `priority` on create** — Create route now reads and persists `priority` from the request body. Previously new buckets always defaulted to `0` regardless of the value submitted.
+- **User bucket page — secret key reveal** — The `/dashboard/bucket` page now shows the actual secret access key with a show/hide toggle (`BucketSecretReveal` client component). All other credentials are hidden behind a "coming soon" notice while direct S3 credential access is being developed.
+- **`reconcileDeprovisionedBuckets` — atomic `Subscription.status` update** — Both cancellation paths (cancelled subscription, subscription not found in Stripe) now use `prisma.$transaction` to atomically update the bucket (`provisionStatus → deprovisioning`), subscription (`status → canceled`), and clear user assignments in a single operation.
+
+### Fixed
+
+- **File serving — wrong storage provider for bucket-routed files** — All file read/stream/delete paths used `getStorageProvider()` (global config bucket singleton) even when the file was stored in a core or dedicated bucket. Affected routes: `GET /api/files/[...path]`, `GET /api/files/[id]/thumbnail`, suggestion approval in `PUT /api/files/[id]/suggestions`, OCR processing, file expiry handler, and single/bulk delete in the file service. All now use `getProviderForStoredFile(file.storageBucketId)`, which routes to the correct bucket and falls back to global for legacy files.
+- **S3 key normalization — Windows backslash paths** — `path.join()` produces backslash-separated paths on Windows (e.g. `uploads\userUrlId\filename.png`). The S3 provider's key derivation regex `/^uploads\//` never matched these, leaving the full backslash path as the S3 key and causing `NoSuchKey` on every read. Added `toS3Key()` helper that normalizes backslashes to forward slashes before stripping the `uploads/` prefix; applied to all five S3 provider methods (`uploadFile`, `getFile`, `getFileStream`, `deleteFile`, `getFileUrl`, `getFileSize`).
+- **Upload path generation — forward slashes enforced** — `app/api/files/route.ts` and `app/api/files/chunks/route.ts` used `path.join()` to build `filePath`, producing backslash paths on Windows that were stored in the database and used as S3 keys. Both now use `path.posix.join()` so paths are always forward-slash regardless of platform.
+- **OCR — wrong bucket** — `processImageOCRTask` called `getStorageProvider()` unconditionally. It now looks up `file.storageBucketId` and routes to `getProviderForStoredFile` so OCR reads from the same bucket the file was uploaded to.
+- **Bucket list — `priority` missing from select** — `GET /api/admin/storage/buckets` did not include `priority` in its field select. The edit dialog received `priority: undefined`, causing the priority input to be uncontrolled (React warning) and saving to silently leave the existing value unchanged.
+- **Edit dialog — uncontrolled `priority` input** — `openEdit` now uses `bucket.priority ?? 0` when populating the form, preventing the React "uncontrolled → controlled" warning when `priority` was absent from the list response.
+- **Dev logger — error detail suppressed** — The development pino transport only printed `obj.msg`, silently dropping `obj.error`. Error message and stack trace are now appended to the console output.
+- **Chunks route — Prisma XOR type error** — `tx.file.create` mixed `storageBucketId` (unchecked input) with `user: { connect: { id } }` (checked input), which Prisma's XOR type rejects. Replaced with `userId` scalar field.
+
+### Changed
+
+- **`getStorageProvider()` scope clarified** — The global singleton is now the fallback only for legacy files (`storageBucketId = null`). All new file operations route through `getProviderForStoredFile` or `getUploadBucketForUser`/`getUploadBucketForSquad`.
+- **`selectCoreBucket` ordering** — Core bucket selection now orders by `fileCount ASC, priority DESC` so higher-priority buckets win when file counts are equal.
+
## [2.4.6] - 2026-06-13
### Security
diff --git a/.github/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
similarity index 100%
rename from .github/CODE_OF_CONDUCT.md
rename to CODE_OF_CONDUCT.md
diff --git a/.github/CONTRIBUTING.md b/CONTRIBUTING.md
similarity index 100%
rename from .github/CONTRIBUTING.md
rename to CONTRIBUTING.md
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..363b285
--- /dev/null
+++ b/README.md
@@ -0,0 +1,199 @@
+# Emberly
+
+Emberly is an open-source platform for modern file storage, sharing, discovery, and identity verification. Build your digital presence with powerful tools for teams and individuals.
+
+[](https://github.com/EmberlyOSS/Emberly/actions/workflows/build.yml) [](https://github.com/EmberlyOSS/Emberly/actions/workflows/codeql.yml)  [](https://app.fossa.com/projects/git%2Bgithub.com%2FEmberlyOSS%2FEmberly?ref=badge_shield&issueType=security)
+
+## Features
+
+**File Storage & Sharing**
+
+- S3-compatible object storage with configurable upload limits
+- Secure file sharing with customizable access controls
+- File organization, tagging, and search
+- OCR-powered text extraction from uploaded images and documents
+- URL shortening with redirect tracking
+- Bandwidth-efficient delivery through global infrastructure
+
+**Domain & Branding**
+
+- Custom domain support with annual registration
+- Personal or team branded file-sharing pages
+- Domain SSL certificate management
+- DNS configuration assistance
+
+**Identity & Verification**
+
+- User verification badges with multiple tier options
+- Verification queue with application review system
+- Badge display on public profiles
+- Organization verification for teams
+
+**Team & Collaboration**
+
+- Squad-based team subscriptions with seat-based pricing
+- Granular permission management (roles: `SUPPORT`, `DEVELOPER`, `MODERATOR`, `DESIGNER`, `STAFF`)
+- Team member invitations and management
+- Shared storage pools with usage tracking
+
+**Applications & Trust**
+
+- Staff application system for organizational partnerships
+- Partner program enrollment
+- Verification badge applications
+- Ban appeal process with review workflow
+- Email notifications for all application updates
+
+**Administrative Tools**
+
+- Promo code management with configurable discounts
+- User management dashboard
+- Application review queue with multi-stage triage
+- Service status page ([emberlystat.us](https://emberlystat.us))
+- Analytics and usage reporting
+
+## Quick Start
+
+For contribution guidelines and detailed documentation see [CONTRIBUTING.md](CONTRIBUTING.md).
+
+### Prerequisites
+
+- Node.js 18+
+- [Bun](https://bun.sh/) (recommended package manager)
+- PostgreSQL 14+
+- Redis 6+ (optional for caching and rate limiting)
+
+### Development Setup
+
+```bash
+# Clone the repository
+git clone https://github.com/EmberlyOSS/Emberly.git
+cd Emberly
+
+# Install dependencies
+bun install
+
+# Configure environment
+cp .env.template .env
+# Edit .env with your local configuration
+
+# Initialize database
+bun run db:generate
+bun run db:migrate
+
+# (Optional) Seed subscription plans
+bun run db:seed
+
+# Start development server
+bun dev
+```
+
+The application will be available at `http://localhost:3000`.
+
+## Tech Stack
+
+**Frontend & Framework**
+
+- [Next.js 16](https://nextjs.org/) — React framework with App Router
+- [React 19](https://react.dev/) — UI library
+- [TypeScript](https://www.typescriptlang.org/) — strict-mode type safety
+- [Tailwind CSS](https://tailwindcss.com/) — utility-first styling
+- [shadcn/ui](https://ui.shadcn.com/) — accessible component library
+
+**Backend & Database**
+
+- [PostgreSQL](https://www.postgresql.org/) — relational database
+- [Prisma ORM](https://www.prisma.io/) — database toolkit and migrations
+- [Redis](https://redis.io/) — caching and rate limiting
+- [Stripe](https://stripe.com/) — payment processing
+- [Resend](https://resend.com/) — transactional email delivery
+
+**Infrastructure & Services**
+
+- S3-compatible object storage (AWS S3 / Vultr) — file storage
+- [NextAuth](https://next-auth.js.org/) — authentication (Discord OAuth, GitHub OAuth, credentials)
+- [Sentry](https://sentry.io/) — error tracking and monitoring
+- [VirusTotal](https://www.virustotal.com/) — file scanning on upload
+
+**Development Tools**
+
+- [Bun](https://bun.sh/) — runtime and package manager
+- [ESLint](https://eslint.org/) + [Prettier](https://prettier.io/) — linting and formatting
+- [Husky](https://typicode.github.io/husky/) + [commitlint](https://commitlint.js.org/) — git hooks and commit linting
+
+## Project Structure
+
+```
+app/ Next.js App Router pages and routes
+ (main)/ Public user pages (auth, admin, user profiles)
+ (raw)/ Raw file serving
+ (shorturl)/ Short URL redirects
+ api/ ~180 REST API endpoints
+
+packages/
+ components/ React component library
+ admin/ Admin dashboard components
+ dashboard/ User dashboard
+ auth/ Authentication UI
+ file/ File management UI
+ pricing/ Pricing and plans
+ ui/ shadcn/ui base components
+ hooks/ Custom React hooks
+ use-file-upload.tsx File uploading with progress
+ use-profile.ts User profile data
+ use-user-content.ts User content queries
+ use-file-actions.ts File action handlers
+ lib/ Business logic and integrations
+ api/ API handler wrapper (auth, logging, errors)
+ auth/ NextAuth config and helpers
+ events/ Event system (emitter, consumer, worker, handlers)
+ cache/ Redis helpers
+ storage/ S3 / Vultr integration
+ emails/ Email templates (Resend)
+ stripe/ Payment processing
+ permissions/ RBAC permission helpers
+ nexium/ Team/squad system
+ security/ Security utilities and rate limiting
+ logger/ Pino structured logging
+ types/ Shared TypeScript type definitions
+
+prisma/
+ schema.prisma Database schema
+ migrations/ Migration history
+
+public/ Static assets
+scripts/ Utility scripts (seed, media-kit)
+```
+
+## Contributing
+
+We welcome contributions from the community. Please see [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines including:
+
+- Development environment setup
+- Code standards and conventions
+- Pull request process
+- Commit message format
+- How to report issues
+- Community channels and support
+
+## Support
+
+- **Discord** — [Join our server](https://discord.gg/36spBmzZVB) for real-time discussions
+- **GitHub Discussions** — Ask questions and share ideas
+- **Email** — [hey@embrly.ca](mailto:hey@embrly.ca) for support
+
+## License
+
+This project is licensed under the GNU Affero General Public License v3 (AGPL-3.0). See the [LICENSE](LICENSE) file for details.
+
+## Code of Conduct
+
+This project adheres to the Contributor Covenant Code of Conduct. By participating, you agree to uphold this code. See [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) for the full text.
+
+## Acknowledgments
+
+Thank you to all [contributors](https://github.com/EmberlyOSS/Emberly/graphs/contributors) who have helped make Emberly possible, and to the [open-source projects](https://github.com/EmberlyOSS/Emberly/network/dependencies) that power it.
+
+
+
+
diff --git a/.github/SECURITY.md b/SECURITY.md
similarity index 82%
rename from .github/SECURITY.md
rename to SECURITY.md
index 4ad5cc1..881dc0b 100644
--- a/.github/SECURITY.md
+++ b/SECURITY.md
@@ -6,13 +6,13 @@ Thanks for helping keep Emberly and its users safe.
We provide security fixes for:
-| Version | Supported |
-| --------- | ------- |
-| `main` branch | Yes |
-| `develop` branch | Yes |
-| 2.4.x | Yes |
-| 2.3.x | Yes |
-| < 2.2.x | No |
+| Version | Supported |
+| ---------------- | --------- |
+| `main` branch | Yes |
+| `develop` branch | Yes |
+| 2.4.x | Yes |
+| 2.3.x | Yes |
+| < 2.2.x | No |
## Reporting a Vulnerability
diff --git a/app/(main)/dashboard/bucket/page.tsx b/app/(main)/dashboard/bucket/page.tsx
index 2bb6b20..efba8c6 100644
--- a/app/(main)/dashboard/bucket/page.tsx
+++ b/app/(main)/dashboard/bucket/page.tsx
@@ -1,43 +1,19 @@
import { redirect } from 'next/navigation'
import { getServerSession } from 'next-auth'
-import { AlertTriangle, Key, Server } from 'lucide-react'
+import { AlertTriangle, Clock, Key, Server } from 'lucide-react'
import { authOptions } from '@/packages/lib/auth'
import { prisma } from '@/packages/lib/database/prisma'
import { buildPageMetadata } from '@/packages/lib/embeds/metadata'
import { provisionBucketForUserSubscription } from '@/packages/lib/storage/bucket-provisioning'
import { DashboardShell } from '@/packages/components/dashboard/dashboard-shell'
+import { BucketSecretReveal } from '@/packages/components/dashboard/bucket-secret-reveal'
export const metadata = buildPageMetadata({
title: 'Storage Bucket',
description: 'View your dedicated S3 storage bucket credentials and status.',
})
-function CredentialRow({
- label,
- value,
- mono = true,
-}: {
- label: string
- value: string
- mono?: boolean
-}) {
- return (
-
+
- Keep your credentials safe. Never expose your Secret Key publicly. If
- you believe your credentials have been compromised, contact{' '}
+ Direct S3 credential access is coming soon. In the meantime, your
+ connection credentials were delivered by email when your bucket was
+ assigned. Contact{' '}
support@embrly.ca
{' '}
- immediately.
+ if you need them resent.