Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
23 changes: 23 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# =============================================================================
# Task-Bounty root environment template
# =============================================================================
# This repository has two active workspaces. Prefer workspace-local env files:
#
# frontend/.env.example → copy to frontend/.env.local
# Documents/Task Bounty/.env.example → legacy reference only (not used by app)
#
# DO NOT store real private keys, seed phrases, or production API secrets here.
# DO NOT commit any file named `.env`, `.env.local`, or `.env.*.local`.
# =============================================================================

# --- Frontend (public / safe to expose in the browser) ---
NEXT_PUBLIC_STELLAR_NETWORK=PUBLIC
NEXT_PUBLIC_HORIZON_URL=https://horizon.stellar.org
NEXT_PUBLIC_SOROBAN_RPC_URL=
NEXT_PUBLIC_CONTRACT_ID=

# --- Deploy / ops (server or local shell ONLY — never NEXT_PUBLIC_) ---
# Populate these in your shell or a gitignored `.env.local`, never in git.
# STELLAR_SECRET_KEY=
# STELLAR_NETWORK_PASSPHRASE=
# DEPLOYER_SECRET_KEY=
14 changes: 14 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,16 @@
# Generated dependency vulnerability scan reports (local + CI artifacts)
reports/

# Environment / secrets — never commit real credentials
.env
.env.*
!.env.example
**/.env
**/.env.*
!**/.env.example

# Common secret material
*.pem
*.key
id_rsa
id_ed25519
36 changes: 23 additions & 13 deletions Documents/Task Bounty/.env.example
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
# Private key for deployment (DO NOT commit actual private key)
PRIVATE_KEY=your_private_key_here
# =============================================================================
# LEGACY / REFERENCE ONLY — not consumed by the active Paymesh frontend
# =============================================================================
# The live app uses Stellar/Soroban (see ../../frontend/.env.example).
# This file remains for historical TaskBounty EVM docs under Documents/.
#
# NEVER commit real keys. Replace placeholders locally in a gitignored `.env`.
# =============================================================================

# RPC URLs
MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/your-api-key
SEPOLIA_RPC_URL=https://eth-sepolia.g.alchemy.com/v2/your-api-key
# Deployer / signer secret for local scripts (KEEP OUT OF GIT)
# Example shape only — leave blank in shared templates:
PRIVATE_KEY=

# Etherscan API key for contract verification
ETHERSCAN_API_KEY=your_etherscan_api_key
# Public RPC endpoints (use your own provider URL; do not commit API keys)
MAINNET_RPC_URL=https://eth-mainnet.example/v2/<YOUR_API_KEY>
SEPOLIA_RPC_URL=https://eth-sepolia.example/v2/<YOUR_API_KEY>

# Deployed contract addresses (update after deployment)
BOUNTY_ADDRESS=0x...
RESOLVER_ADDRESS=0x...
FACTORY_ADDRESS=0x...
# Block explorer verification (optional)
ETHERSCAN_API_KEY=

# Arbitrator address (defaults to deployer if not set)
ARBITRATOR=0x...
# Deployed contract addresses (public — fill after deploy)
BOUNTY_ADDRESS=
RESOLVER_ADDRESS=
FACTORY_ADDRESS=

# Optional arbitrator address (public)
ARBITRATOR=
4 changes: 3 additions & 1 deletion Documents/Task Bounty/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ out/
# Docs
docs/

# Dotenv file
# Dotenv files — never commit real secrets
.env
.env.*
!.env.example

# Dependencies
lib/
Expand Down
101 changes: 101 additions & 0 deletions ENVIRONMENT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# Environment Variable Management

This document describes how Task-Bounty manages configuration and secrets so that
sensitive values are never committed or leaked to the browser.

## Acceptance checklist

- [x] `.env.example` templates updated (root + frontend + legacy docs)
- [x] Sensitive values removed from committed templates
- [x] Documentation for safe env usage (this file)

## Source of truth

| File | Purpose | Commit? |
|------|---------|---------|
| [`frontend/.env.example`](frontend/.env.example) | Active Next.js app template | Yes |
| [`.env.example`](.env.example) | Root overview / pointers | Yes |
| [`Documents/Task Bounty/.env.example`](Documents/Task%20Bounty/.env.example) | Legacy EVM reference only | Yes |
| `frontend/.env.local` / `.env` / `.env.*.local` | Real local secrets & overrides | **Never** |

## Rules

1. **Never commit secrets.** Private keys, seed phrases, deployer secrets, and
provider API tokens must live only in gitignored files or a secret manager.
2. **Never put secrets in `NEXT_PUBLIC_*` variables.** Anything with that prefix
is bundled into client JavaScript and is publicly readable.
3. **Use placeholders in examples.** Templates may show empty values or
`<YOUR_API_KEY>` markers — never real credentials.
4. **Prefer workspace-local files.** Frontend config belongs in `frontend/.env.local`.
5. **Defaults must be safe.** The app boots without a local env file by using
public Stellar defaults (Horizon mainnet URL, `PUBLIC` network).

## Frontend variables

| Variable | Public? | Description |
|----------|---------|-------------|
| `NEXT_PUBLIC_STELLAR_NETWORK` | Yes | `PUBLIC` or `TESTNET` for the wallet kit |
| `NEXT_PUBLIC_HORIZON_URL` | Yes | Horizon HTTP base URL for account reads |
| `NEXT_PUBLIC_SOROBAN_RPC_URL` | Yes | Optional Soroban RPC URL (future contract calls) |
| `NEXT_PUBLIC_CONTRACT_ID` | Yes | Optional deployed contract ID (`C...`) |
| `NODE_ENV` | Yes | Set by Next.js / Node — do not override with secrets |

Server-only secrets (if introduced later) must:

- omit the `NEXT_PUBLIC_` prefix
- be read only inside Route Handlers / Server Components / server utilities
- never be logged or returned in API responses

## Local setup

```bash
cd frontend
cp .env.example .env.local
# edit .env.local with non-secret public overrides as needed
pnpm dev
```

Confirm `.env.local` is ignored:

```bash
git check-ignore -v frontend/.env.local
```

## Contract / deploy secrets

Soroban deploy keys and network secrets belong in your shell environment or a
password manager — not in the frontend bundle:

```bash
# Example: export for a single shell session (do not commit)
export STELLAR_SECRET_KEY="S..." # your key — never paste into git
stellar contract deploy --source-account "$STELLAR_SECRET_KEY" ...
```

The AutoShare contract workspace under `contract/` does not require a committed
`.env` file for `cargo test` / `cargo build`.

## What was removed / hardened

- Legacy `Documents/Task Bounty/.env.example` no longer embeds sample Alchemy URL
paths that looked like filled API slots; keys are blank placeholders.
- `PRIVATE_KEY` and explorer API keys are empty in templates.
- Frontend gitignore allows committing `.env.example` while still ignoring
`.env`, `.env.local`, and `.env.*.local`.
- Root gitignore blocks common secret env filenames repo-wide.

## Verification helpers

```bash
# Ensure example files contain no high-entropy secret-looking assignments
cd frontend && pnpm test -- src/lib/env.test.ts

# Production build must succeed with defaults (no .env.local required)
pnpm build
```

## Related docs

- [SECURITY.md](SECURITY.md) — vulnerability reporting and product security posture
- [SETUP.md](SETUP.md) — local install and run instructions
- [SECURITY_HEADERS.md](SECURITY_HEADERS.md) — HTTP header configuration
6 changes: 5 additions & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,11 @@ We provide security updates for the following versions:
- HTTP Security Headers (CSP, HSTS, X-Frame-Options) are enforced on all responses
- Input validation on all user-facing forms
- Wallet integration follows Stellar Wallets Kit security best practices
- Environment variables are never exposed in frontend code
- Environment variable management:
- Secrets must never be committed (see [ENVIRONMENT.md](ENVIRONMENT.md))
- Only `NEXT_PUBLIC_*` values may reach the browser — treat them as public
- Private keys, mnemonics, and API tokens must stay in gitignored `.env.local` files or a secret manager
- Templates live in `.env.example` with empty / placeholder values only

### Blockchain-Specific Concerns

Expand Down
27 changes: 21 additions & 6 deletions SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,22 +147,37 @@ cd ..

### Frontend configuration

The current frontend does **not** require a `.env.local` file to boot.
Copy the example env file if you want local overrides (optional — defaults work out of the box):

At the moment:
```bash
cd frontend
cp .env.example .env.local
```

Public configuration is documented in [ENVIRONMENT.md](ENVIRONMENT.md). Important rules:

- **Never commit** `.env`, `.env.local`, or real private keys
- **Never put secrets** in `NEXT_PUBLIC_*` variables (they ship to the browser)
- Defaults: Horizon `https://horizon.stellar.org`, wallet network `PUBLIC`

At the moment the frontend reads:

- wallet network is set in `frontend/src/hooks/stellar-wallets-kit.ts`
- Horizon endpoint is set in `frontend/src/lib/stellar.ts`
| Variable | Used by |
|----------|---------|
| `NEXT_PUBLIC_STELLAR_NETWORK` | `frontend/src/hooks/stellar-wallets-kit.ts` |
| `NEXT_PUBLIC_HORIZON_URL` | `frontend/src/lib/stellar.ts` |
| `NEXT_PUBLIC_SOROBAN_RPC_URL` | reserved for future contract clients |
| `NEXT_PUBLIC_CONTRACT_ID` | reserved for future contract clients |

That means the old file below is **reference-only** and is not consumed by the current frontend:
The legacy file below is **reference-only** and is **not** consumed by the current frontend:

```text
Documents/Task Bounty/.env.example
```

### When you may still want local configuration

You may choose to add a private `.env.local` later if you wire contract IDs, RPC URLs, or feature flags into the frontend. Until the code reads those variables, creating the file has no effect.
Use `frontend/.env.local` to point at Testnet Horizon, a custom RPC URL, or a deployed contract ID without changing source. Keep deployer secrets in your shell or password manager — not in the frontend env file.

---

Expand Down
7 changes: 6 additions & 1 deletion contract/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,9 @@ target
# Local settings
.soroban
.stellar
test_snapshots
test_snapshots

# Environment / secrets
.env
.env.*
!.env.example
30 changes: 30 additions & 0 deletions frontend/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# =============================================================================
# Frontend environment variables (Task-Bounty / Paymesh)
# =============================================================================
# Copy this file to `.env.local` for local overrides:
# cp .env.example .env.local
#
# Rules:
# - NEVER put secret keys, mnemonics, or private API tokens in this file.
# - NEVER commit `.env`, `.env.local`, or `.env*.local`.
# - Only `NEXT_PUBLIC_*` values are readable in the browser. Treat them as public.
# - Server-only secrets (if added later) must NOT use the NEXT_PUBLIC_ prefix.
# =============================================================================

# Stellar network used by the wallet kit.
# Allowed values: PUBLIC | TESTNET
NEXT_PUBLIC_STELLAR_NETWORK=PUBLIC

# Horizon HTTP API used for account/balance reads (public endpoint).
NEXT_PUBLIC_HORIZON_URL=https://horizon.stellar.org

# Optional Soroban RPC endpoint for future contract client wiring.
# Leave empty until the frontend invokes contracts directly.
NEXT_PUBLIC_SOROBAN_RPC_URL=

# Optional deployed AutoShare / TaskBounty contract ID (C...).
# Leave empty until the UI is wired to on-chain calls.
NEXT_PUBLIC_CONTRACT_ID=

# Optional app environment label for diagnostics (not a secret).
# NODE_ENV is set automatically by Next.js (development | production | test).
4 changes: 3 additions & 1 deletion frontend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*
.env
.env.*
!.env.example

# vercel
.vercel
Expand Down
6 changes: 6 additions & 0 deletions frontend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,12 @@ Example response (`200 OK`, `Cache-Control: no-store`):

The endpoint is always server-rendered (never cached), so it reflects the live process. It can be wired into load balancers, uptime monitors, or container orchestration probes.

## Environment variables

Copy [`.env.example`](./.env.example) to `.env.local` for optional public overrides (network, Horizon URL, contract ID).

**Never commit secrets.** See [`../ENVIRONMENT.md`](../ENVIRONMENT.md) for the full policy. Only `NEXT_PUBLIC_*` values are available in the browser — do not put private keys or API tokens there.

## Running Tests

Unit tests are written with [Vitest](https://vitest.dev):
Expand Down
9 changes: 8 additions & 1 deletion frontend/src/hooks/stellar-wallets-kit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
WalletNetwork,
} from "@creit.tech/stellar-wallets-kit";
import { createError, ErrorCodes } from "@/lib/errors";
import { getPublicEnv } from "@/lib/env";

const SELECTED_WALLET_ID = "selectedWalletId";

Expand All @@ -13,6 +14,12 @@ function getSelectedWalletId() {
return localStorage.getItem(SELECTED_WALLET_ID);
}

function resolveWalletNetwork() {
return getPublicEnv().stellarNetwork === "TESTNET"
? WalletNetwork.TESTNET
: WalletNetwork.PUBLIC;
}

let kit: StellarWalletsKit | null = null;

function getKit(): StellarWalletsKit | null {
Expand All @@ -21,7 +28,7 @@ function getKit(): StellarWalletsKit | null {
if (typeof window !== "undefined") {
kit = new StellarWalletsKit({
modules: allowAllModules(),
network: WalletNetwork.PUBLIC,
network: resolveWalletNetwork(),
selectedWalletId: getSelectedWalletId() ?? FREIGHTER_ID,
});
return kit;
Expand Down
Loading
Loading