Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
2296bc6
chore: move to shadcn/ui on Tailwind v4 with a shared design system
ChirayuSahu Nov 7, 2026
eda270b
fix(security): AES-256-GCM encryption and working per-IP rate limits
ChirayuSahu Nov 7, 2026
c212c12
feat: organizations, teams, projects and environments data model
ChirayuSahu Nov 7, 2026
a67ed72
feat(auth): mandatory TOTP two-factor and password sign-up
ChirayuSahu Nov 7, 2026
bf41120
feat(api): organization, team, project and environment APIs
ChirayuSahu Nov 7, 2026
b6878cb
feat: invite codes and onboarding
ChirayuSahu Nov 7, 2026
af3dc20
feat: temporary share links that always expire
ChirayuSahu Nov 7, 2026
790cf08
feat(app): app shell with org, team and project pages
ChirayuSahu Nov 7, 2026
746aae8
feat(landing): new landing page
ChirayuSahu Nov 7, 2026
4346595
feat: migrate workspaces and groups to organizations
ChirayuSahu Nov 7, 2026
31a1e39
docs: update README for organizations, 2FA and the new API
ChirayuSahu Nov 7, 2026
f85f855
Merge pull request #1 from ChirayuSahu/feat/orgs-teams-2fa
ChirayuSahu Nov 7, 2026
6330a5c
fix(build): clean production build on Vercel
ChirayuSahu Nov 7, 2026
c63f409
fix(migration): dry run no longer creates collections or indexes
ChirayuSahu Nov 7, 2026
66211ac
fix(deps): upgrade Next.js to 15.5.29 and patch vulnerable dependencies
ChirayuSahu Nov 7, 2026
ae69aad
docs: point README at GDGVIT/envoy and say GDG VIT
ChirayuSahu Nov 7, 2026
d644436
feat(landing): brand-green footer and GDGVIT repo links
ChirayuSahu Nov 7, 2026
2bf23ce
fix(landing): align the use-case tiles in a 2x2 grid
ChirayuSahu Nov 7, 2026
12fa25c
feat: typed confirmation for every deletion
ChirayuSahu Nov 7, 2026
a5a55ee
fix(migration): decrypt with the right legacy secret, and repair on r…
ChirayuSahu Nov 7, 2026
edcdc06
feat: 404 and error pages, and clearer load failures
ChirayuSahu Nov 7, 2026
a846076
feat: centre error and not-found states
ChirayuSahu Nov 7, 2026
3165945
feat: custom expiry dates for API tokens and invite links
ChirayuSahu Nov 7, 2026
5b5105c
feat: ask for an authenticator code before showing secret values
ChirayuSahu Nov 7, 2026
b428eaf
feat: one dialog style, selects that open below, grouped buttons
ChirayuSahu Nov 7, 2026
fbd8924
feat: temporary links use the app's variables table, and say when the…
ChirayuSahu Nov 7, 2026
56ca849
feat: command menu searches environments and variable names
ChirayuSahu Nov 7, 2026
df11845
feat: passkeys, optional two-factor, and an org setting to require it
ChirayuSahu Nov 7, 2026
815480f
feat: sign up with Google only; set a password in Account settings
ChirayuSahu Nov 7, 2026
3f45e1a
feat: projects limited to selected people, moving projects between te…
ChirayuSahu Nov 7, 2026
8796d93
chore: remove the old workspace and group code
ChirayuSahu Nov 7, 2026
3bc66ba
fix: switch thumb, clearer Security card, shadcn date picker
ChirayuSahu Nov 7, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
193 changes: 107 additions & 86 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<p align="center">
<a href="https://dscvit.com">
<img width="400" src="https://user-images.githubusercontent.com/56252312/159312411-58410727-3933-4224-b43e-4e9b627838a3.png#gh-light-mode-only" alt="GDSC VIT"/>
<img width="400" src="https://user-images.githubusercontent.com/56252312/159312411-58410727-3933-4224-b43e-4e9b627838a3.png#gh-light-mode-only" alt="GDG VIT"/>
</a>
<h2 align="center">Envoy - Secure Environment Variable Management</h2>
<h4 align="center">A secure platform for managing and sharing environment variables across development teams<h4>
Expand All @@ -10,97 +10,82 @@
[![Join Us](https://img.shields.io/badge/Join%20Us-Developer%20Student%20Clubs-red)](https://dsc.community.dev/vellore-institute-of-technology/)
[![Discord Chat](https://img.shields.io/discord/760928671698649098.svg)](https://discord.gg/498KVdSKWR)

[![DOCS](https://img.shields.io/badge/Documentation-see%20docs-green?style=flat-square&logo=appveyor)](https://github.com/GDGVIT/env-sharing)
[![DOCS](https://img.shields.io/badge/Documentation-see%20docs-green?style=flat-square&logo=appveyor)](https://github.com/GDGVIT/envoy)
[![UI ](https://img.shields.io/badge/User%20Interface-Link%20to%20UI-orange?style=flat-square&logo=appveyor)](https://env-sharing-platform.vercel.app)

## Overview

The Environment Sharing Platform is a secure web application that enables development teams to safely manage, store, and share environment variables without exposing sensitive credentials through insecure channels like Slack or email. Built with Next.js and MongoDB, it provides an encrypted, centralized vault for all your environment variables.

### How it's organized

```
Organization owners, admins and members
└ Team each member is an Editor or a Viewer
└ Project one app or service
└ Environment development, staging, production, … (each with its own variables)
```

| Role | Can do |
| --- | --- |
| **Org owner** | Everything, plus delete the org, transfer ownership, require two-factor, reset a member's 2FA |
| **Org admin** | Create teams, invite people, change roles, edit every project, view the audit log |
| **Org member** | See only the teams they're on |
| **Team editor** | Read and change variables, create projects and environments in that team |
| **Team viewer** | Read variables only |

## Features
- [x] **Secure Environment Variable Storage** - Encrypted storage of API keys, database credentials, and other sensitive configuration data
- [x] **Team Collaboration** - Create workspaces and groups to organize and share environment variables with team members
- [x] **Role-based Access Control** - Owner and member roles with appropriate permissions for workspace and group management
- [x] **Authentication System** - Secure user registration and login with NextAuth.js integration
- [x] **Workspace Management** - Create, edit, and delete workspaces to organize your projects
- [x] **Group Management** - Organize environment variables into groups within workspaces
- [x] **Member Management** - Add and remove team members from groups and workspaces
- [x] **Sharing Tokens** - Generate secure tokens for sharing environment variables
- [x] **Dark/Light Theme** - Toggle between dark and light themes for better user experience
- [x] **Responsive Design** - Fully responsive design that works on desktop and mobile devices
- [x] **Organizations, teams and projects** - Org owners and admins create teams and decide who can edit and who can only read
- [x] **Multiple environments per project** - development, staging and production out of the box; add your own
- [x] **Sign in with Google** - Accounts are created with Google; people can add a password in Account settings for email sign-in
- [x] **Passkeys and authenticator apps** - Optional second step at sign-in (Touch ID, Face ID, Windows Hello, a password manager, or 6-digit codes), with one-time backup codes. Owners can require it for their organization
- [x] **Values stay hidden until you confirm** - People with two-factor confirm with a passkey or code before secret values are sent to the browser; the unlock lasts 10 minutes and lives on the server
- [x] **Restricted projects** - Limit a project to selected team members; move projects between teams
- [x] **Invitations** - 10-character invite codes (also shareable as a link) that expire and can be limited to a number of uses. Envoy doesn't send email.
- [x] **Audit log** - Owners and admins see every change to members, teams, projects and variables (key names only, never values)
- [x] **Personal API tokens** - Fetch variables from the CLI or CI; tokens follow the user's current access
- [x] **Encrypted at rest** - AES-256-GCM, decrypted only for people with access
- [x] **Safe concurrent editing** - Saves are versioned, so two editors can't silently overwrite each other
- [x] **Temporary links** - Share a .env once without an account; links expire within 24 hours and are deleted. Environments are never public.
- [x] **Monochrome UI** - shadcn/ui, dark and light themes, ⌘K command menu, keyboard shortcuts, responsive down to mobile
- [x] **Rate Limiting** - Built-in rate limiting to prevent abuse and ensure system stability
- [ ] **NodeJS and Python SDK** - Fetch enviornment variables directly from the terminal
- [ ] **Basic Groups** - Create basic groups with limited features
- [ ] **NodeJS and Python SDK** - Fetch environment variables directly from the terminal

<br>

## Tech Stack

### Frontend
- **Next.js 15** - React framework for production
- **React 18** - JavaScript library for building user interfaces
- **TypeScript 5** - Typed superset of JavaScript
- **Tailwind CSS 4** - Utility-first CSS framework
- **Lucide React** - Beautiful & consistent icon toolkit
- **Next Themes** - Perfect dark mode in 2 lines of code
- **Next.js 15** (App Router) and **TypeScript 5**
- **shadcn/ui** (Radix primitives) with **Tailwind CSS 4**, monochrome theme tokens in `src/app/globals.css`
- **Geist Sans / Geist Mono** fonts, **Lucide** icons, **cmdk** command menu, **sonner** toasts
- **SWR** for client data fetching, **next-themes** for dark/light

### Backend
- **Next.js API Routes** - Serverless API endpoints
- **MongoDB** - NoSQL database for data storage
- **Mongoose** - MongoDB object modeling for Node.js
- **NextAuth.js** - Complete open source authentication solution

### Security & Utilities
- **bcryptjs** - Password hashing library
- **crypto-js** - Cryptographic algorithms for data encryption
- **rate-limiter-flexible** - Rate limiting middleware
- **custom-uuid** - UUID generation for unique identifiers

### Development Tools
- **ESLint** - JavaScript linter
- **PostCSS** - Tool for transforming CSS with JavaScript
- **Autoprefixer** - PostCSS plugin to parse CSS and add vendor prefixes

## Dependencies

### Production Dependencies
- next (^15.3.5)
- react (18.2.0)
- react-dom (18.2.0)
- mongoose (^8.15.1)
- next-auth (^4.24.11)
- bcryptjs (^3.0.2)
- crypto-js (^4.2.0)
- tailwindcss (^4.0.0)
- next-themes (^0.4.6)
- lucide-react (^0.522.0)
- rate-limiter-flexible (^7.1.1)
- sonner (^2.0.6)
- custom-uuid (^3.1.1)
- clsx (^2.1.1)

### Development Dependencies
- typescript (^5)
- @types/node (^20)
- @types/react (^19)
- @types/react-dom (^19)
- @types/crypto-js (^4.2.2)
- eslint (^8.56.0)
- eslint-config-next (15.3.2)
- **Next.js route handlers** under `src/app/api`
- **MongoDB** with **Mongoose**
- **NextAuth.js** (Google + email/password) with an optional passkey or TOTP second factor

### Security
- **SimpleWebAuthn** for passkeys (only public keys stored, single-use challenges)
- **otpauth** + **qrcode** for TOTP enrollment and verification (replay-protected, rate-limited)
- **bcryptjs** for password hashing; backup codes and API tokens are stored as SHA-256 hashes
- **Node `crypto` AES-256-GCM** for values at rest (`crypto-js` only to read legacy values)
- **zod** request validation, **rate-limiter-flexible** rate limiting

## Running

### Prerequisites
- Node.js (v18 or higher)
- Node.js 20.12 or newer
- MongoDB database
- npm or yarn package manager

### Installation

1. Clone the repository:
```bash
git clone https://github.com/GDGVIT/env-sharing.git
cd env-sharing/web-app
git clone https://github.com/GDGVIT/envoy.git
cd envoy/web-app
```

2. Install dependencies:
Expand All @@ -122,13 +107,17 @@ NEXTAUTH_SECRET=your_nextauth_secret
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret

# Encryption
NEXT_PUBLIC_ENCRYPTION_SECRET=your_32_character_encryption_key
# Encryption (server only; use a long random value and keep it backed up)
ENCRYPTION_SECRET=your_long_random_encryption_key

#Others
NEXT_PUBLIC_APP_NAME=your_app_name
```

`ENCRYPTION_SECRET` is used only by server-side code and must stay the same for as long as encrypted data needs to be read: it encrypts variable values, temporary links and authenticator-app secrets. Changing it makes that data unreadable (nothing is deleted; restoring the old value fixes it), so keep it backed up.

Optional: `WEBAUTHN_RP_ID` and `WEBAUTHN_ORIGIN` pin passkeys to one domain (e.g. `envoy.example.com` and `https://envoy.example.com`). Without them, passkeys belong to whichever domain they were created on.

### Development

Start the development server:
Expand All @@ -146,34 +135,66 @@ npm run build
npm start
```

### Linting
### Linting and type checks

Run ESLint to check for code quality issues:
```bash
npm run lint
npm run typecheck
```

## CLI & API access

1. In the app, open **Account → API tokens** and create a token.
2. Fetch an environment (every project page has a **Use from CLI** button with the exact URL):

```bash
export ENVOY_TOKEN=envoy_pat_…

# write a .env file
curl -fsS -H "Authorization: Bearer $ENVOY_TOKEN" \
"https://your-envoy-host/api/v1/<org>/<team>/<project>/<environment>?format=dotenv" > .env

# or get JSON: { "vars": { "KEY": "value" }, "version": 3, … }
curl -fsS -H "Authorization: Bearer $ENVOY_TOKEN" \
"https://your-envoy-host/api/v1/<org>/<team>/<project>/<environment>"
```

Tokens act with the owner's *current* access: removing someone from a team (or the org) immediately cuts off their tokens too. Revoke a token from the same page.

### Pagination

List endpoints (organizations, members, team projects and members, invite links, API tokens, audit log) return one page at a time:

- `?limit=` sets the page size: default 50, at most 100.
- Each response includes `nextCursor`. Pass it back as `?cursor=` to get the next page; it is `null` on the last page.
- Cursors are opaque and stay stable when items are added or removed between requests.
- Some lists also return `total`. Org members accept `?q=` to search by name or email.

## Breaking changes from the workspaces/groups version

Envoy used to organize variables as Workspaces → Groups. Existing data has been moved to Organizations → Teams → Projects → Environments.
- Group tokens no longer work. `GET /api/env/get` returns `410 Gone`; use personal API tokens and `/api/v1/…`.
- Nothing can be made public. Use invite links, or temporary links (at most 24 hours) for one-off sharing.
- Invitations are 10-character codes (`XXXXX-XXXXX`), also usable as an `/invite/<code>` link. Envoy doesn't send email invites.

## Project Structure

```
web-app/
├── src/
│ ├── app/ # App router pages and API routes
│ │ ├── api/ # API endpoints
│ │ │ ├── (auth)/ # Authentication routes
│ │ │ └── (user)/ # User-related routes
│ │ ├── dashboard/ # Dashboard pages
│ │ ├── login/ # Login page
│ │ └── signup/ # Signup page
│ ├── components/ # Reusable React components
│ │ ├── dashboard/ # Dashboard-specific components
│ │ └── misc/ # Miscellaneous components
│ ├── models/ # MongoDB schemas
│ ├── providers/ # React context providers
│ ├── types/ # TypeScript type definitions
│ └── utils/ # Utility functions
├── public/ # Static assets
└── package.json # Project dependencies and scripts
│ ├── app/
│ │ ├── (auth)/ # login, signup, 2FA setup/verify, onboarding, invite links
│ │ ├── (app)/ # signed-in app: /o/[org]/…, /account
│ │ ├── share/ # temporary links (expire within 24h)
│ │ └── api/ # route handlers (orgs, teams, projects, envs, invites, tokens, 2fa, v1)
│ ├── components/
│ │ ├── ui/ # shadcn/ui components
│ │ ├── app/ # app shell, env editor, command menu
│ │ └── landing/ # marketing page
│ ├── lib/ # auth, authorization, audit, totp, validation, dotenv
│ ├── models/ # Mongoose schemas
│ └── utils/ # encryption, rate limiting, db connection
└── public/
```

## Contributors
Expand Down Expand Up @@ -214,5 +235,5 @@ web-app/
</table>

<p align="center">
Made with ❤ by <a href="https://dscvit.com">GDSC-VIT</a>
Made with ❤ by <a href="https://dscvit.com">GDG VIT</a>
</p>
25 changes: 25 additions & 0 deletions web-app/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "radix-nova",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"iconLibrary": "lucide",
"rtl": false,
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"menuColor": "default",
"menuAccent": "subtle",
"registries": {}
}
6 changes: 5 additions & 1 deletion web-app/next.config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
/* config options here */
// Keep the dev-only Next.js indicator away from the sidebar account menu (bottom-left).
devIndicators: { position: "bottom-right" },
// Loaded by Node at runtime instead of bundled: the package lists optional storage backends
// (e.g. drizzle-orm) that Envoy doesn't use, and bundling it fails to resolve them.
serverExternalPackages: ["rate-limiter-flexible"],
};

export default nextConfig;
Loading
Loading