# Gemini Consultation: firefrost-services Monorepo Architecture
## Architectural Decision Record

**Date:** March 31, 2026  
**Participants:** Michael (The Wizard), Claude (The Golden Chronicler #50), Gemini (Architectural Consultant)  
**Topic:** Monorepo structure and version management strategy for Firefrost Gaming backend services  
**Decision Status:** ✅ APPROVED — Ready for implementation  
**Related Task:** Task #87 (Arbiter 2.1 deployment will be first service in new structure)

---

## Context

Firefrost Gaming has developed multiple custom Node.js backend services:
- **Arbiter** — Discord bot for subscription automation and role management
- **Whitelist Manager** — Pterodactyl Panel integration for Minecraft whitelist automation
- **Modpack Version Checker** — Monitors modpack updates across game servers
- **Future services** — Additional tools and integrations planned

These services currently exist as separate, unversioned deployments. We need a sustainable monorepo structure that:
- Supports remote management from RV (September 2027 goal)
- Works with simple `git pull` workflow (Chromebook accessibility requirement)
- Handles service-specific versioning
- Enables code sharing between services
- Aligns with industry best practices

---

## The Question

**Should we use directory-based version archives or Git tags for version management?**

### Approach A: Directory-Based Versions
```
firefrost-services/
├── arbiter/
│   ├── current/
│   ├── v2.1/
│   ├── v2.0/
│   └── archive/
```

**Pros:** Visual history, easy comparison  
**Cons:** Code duplication, breaks Node.js module resolution, anti-pattern

### Approach B: Git Tags for Versions
```
firefrost-services/
├── arbiter/
│   ├── src/
│   └── package.json
```

With service-prefixed tags: `arbiter-v2.1.0`, `whitelist-v1.0.0`

**Pros:** Native Git features, clean tree, industry standard  
**Cons:** Less visible (but proper use of Git)

---

## Gemini's Recommendation

**✅ Approach B (Git Tags) is the definitive winner.**

### Key Reasoning

**Directory-based versioning is an anti-pattern:**
- Bloats repository size
- Makes line-by-line change tracking impossible
- Breaks standard Node.js module resolution
- Not how Git is designed to work

**Git tags are purpose-built for versioning:**
- Clean codebase structure
- Full history via `git log`
- Easy rollbacks via `git checkout <tag>`
- Industry standard approach

---

## Approved Architecture

### Repository Structure

```
firefrost-services/
├── package.json              # Root workspace configuration
├── package-lock.json
├── .gitignore
├── README.md                 # Monorepo overview
├── services/
│   ├── arbiter/
│   │   ├── src/
│   │   │   └── index.js
│   │   ├── deploy/
│   │   │   └── arbiter.service
│   │   ├── .env.example
│   │   ├── package.json
│   │   └── README.md
│   ├── whitelist-manager/
│   └── modpack-version-checker/
├── shared/
│   ├── src/
│   │   ├── utils/
│   │   └── logger/
│   ├── package.json          # Named "@firefrost/shared"
│   └── README.md
└── future/                   # Experimental ideas
    └── README.md
```

### Version Management Strategy

**Service-Prefixed Git Tags:**
- Arbiter releases: `arbiter-v2.1.0`, `arbiter-v2.2.0`
- Whitelist Manager: `whitelist-v1.0.0`, `whitelist-v1.1.0`
- Modpack Checker: `modpack-v1.0.0`

This solves the "Service A is v2.1, Service B is v1.0" problem perfectly.

### npm Workspaces Configuration

**Root package.json:**
```json
{
  "name": "firefrost-services",
  "private": true,
  "workspaces": [
    "services/*",
    "shared"
  ]
}
```

**Shared package (shared/package.json):**
```json
{
  "name": "@firefrost/shared",
  "version": "1.0.0",
  "main": "src/index.js"
}
```

**Service dependency (services/arbiter/package.json):**
```json
{
  "name": "@firefrost/arbiter",
  "dependencies": {
    "discord.js": "^14.0.0",
    "@firefrost/shared": "*"
  }
}
```

**Key benefit:** Single `npm install` at root handles all services and shared code automatically.

---

## Deployment Workflow

### Standard Deployment (Update to Newer Version)

```bash
# On the server running Arbiter
cd /var/www/firefrost-services

# Step 1: Fetch latest tags
git fetch --all --tags

# Step 2: Check out specific version
git checkout arbiter-v2.1.0

# Step 3: Install dependencies
npm install

# Step 4: Restart service
sudo systemctl restart arbiter
```

### Rollback Workflow

```bash
# Step 1: Return to main branch
git checkout main

# Step 2: Pull latest
git pull origin main

# Step 3: Check out rollback version
git checkout arbiter-v2.0.0

# Step 4: Restart service
sudo systemctl restart arbiter
```

### Critical: Detached HEAD State

When you `git checkout <tag>`, Git enters "detached HEAD" state (static snapshot).

**Important:** You cannot run `git pull` while in detached HEAD state.

To update, you must return to main branch first, pull, then checkout the new tag.

---

## systemd Configuration

**Correct configuration for monorepo services:**

```ini
[Unit]
Description=Arbiter Discord Bot
After=network.target

[Service]
Type=simple
User=arbiter
WorkingDirectory=/var/www/firefrost-services/services/arbiter
ExecStart=/usr/bin/node src/index.js
Restart=always
RestartSec=10
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
```

**Key change from standalone deployment:**
- `WorkingDirectory` set to service folder (not repo root)
- `ExecStart` uses relative path from WorkingDirectory
- This ensures proper file resolution and environment variable loading

---

## Environment Variables Strategy

**Approved approach:** `.env.example` committed + `.gitignore` for actual `.env`

### Implementation

1. **Create `.env.example` in each service directory** (committed to Git):
   ```
   DISCORD_TOKEN=your_token_here
   PAYMENTER_WEBHOOK_SECRET=your_secret_here
   DATABASE_URL=postgresql://user:pass@host:port/db
   ```

2. **Add `.env` to root `.gitignore`** (prevents accidental commits):
   ```
   .env
   node_modules/
   ```

3. **On server, manually create actual `.env`** in service directory with real credentials

**Why this works:**
- ✅ Secrets never committed to Git
- ✅ Configuration template visible to developers
- ✅ Industry standard approach
- ✅ Easy to document what each service needs

---

## Multi-Server Deployment

**Scenario:** Arbiter runs on Server A, Whitelist Manager runs on Server B

### Process

1. **Clone entire repo to both servers:**
   ```bash
   # Server A (Command Center)
   git clone https://token@git.firefrostgaming.com/firefrost-gaming/firefrost-services.git
   
   # Server B (Panel VPS)
   git clone https://token@git.firefrostgaming.com/firefrost-gaming/firefrost-services.git
   ```

2. **Server A deployment (Arbiter only):**
   ```bash
   cd firefrost-services
   git checkout arbiter-v2.1.0
   npm install
   # Create services/arbiter/.env with actual tokens
   sudo systemctl enable arbiter
   sudo systemctl start arbiter
   ```

3. **Server B deployment (Whitelist Manager only):**
   ```bash
   cd firefrost-services
   git checkout whitelist-v1.0.0
   npm install
   # Create services/whitelist-manager/.env with actual tokens
   sudo systemctl enable whitelist-manager
   sudo systemctl start whitelist-manager
   ```

**Result:** Entire codebase exists on both servers, but only the specific service configured in systemd runs on each.

---

## Key Principles Established

### 1. Simplicity Over Complexity
- Native npm workspaces (no Lerna, Nx, or Turborepo)
- Standard Git features (no custom versioning tools)
- Direct systemd management (no PM2 or other process managers)

### 2. Security First
- Secrets never committed to Git
- `.env.example` templates for documentation
- Manual `.env` creation on servers

### 3. Service Independence
- Services never import from other services directly
- Shared code lives in `@firefrost/shared` package
- Each service can version independently

### 4. Sustainability
- Structure supports decades-long maintenance
- Simple enough to manage remotely from RV
- Clear rollback procedures

### 5. Accessibility
- Works with `git pull` workflow (Chromebook compatible)
- Minimal typing required for deployments
- Clear, documented procedures

---

## Anti-Patterns to Avoid

**Gemini explicitly warned against:**

1. **Service interdependency** — Never import code directly from other services. Use `@firefrost/shared` instead.

2. **Over-complicated tooling** — Don't reach for Lerna/Nx/Turborepo for a small team. Standard npm workspaces are sufficient.

3. **Stale systemd paths** — Always update `WorkingDirectory` and `ExecStart` to match new monorepo structure.

4. **Secrets in Git** — Never put actual `.env` files in repository, even temporarily.

---

## Implementation Plan

### Phase 1: Repository Setup
1. Create `firefrost-services` repo in Gitea
2. Set up directory structure
3. Create root `package.json` with workspaces
4. Add `.gitignore` and README

### Phase 2: Arbiter 2.1 Migration (First Service)
1. Move Arbiter 2.1 code into `services/arbiter/`
2. Create `@firefrost/shared` package
3. Update systemd configuration
4. Test deployment workflow
5. Tag as `arbiter-v2.1.0`

### Phase 3: Additional Services
1. Migrate Whitelist Manager
2. Migrate Modpack Version Checker
3. Tag each with appropriate versions

### Phase 4: Future Development
1. Add experimental services to `future/`
2. Document service creation process
3. Establish CI/CD if needed

---

## Success Metrics

**This architecture is successful if:**
- ✅ Single `npm install` deploys all services
- ✅ Rollbacks take <5 minutes
- ✅ New services can be added without restructuring
- ✅ Documentation is clear enough for future staff
- ✅ Michael can manage from RV in 2027

---

## Related Documentation

- **Task #87:** `docs/tasks/arbiter-2-1-cancellation-flow/README.md` (Arbiter 2.1 architecture)
- **Gemini Session Transcript:** This document
- **Operations Manual:** `docs/core/infrastructure-manifest.md` (will be updated post-deployment)

---

## Acknowledgments

**Gemini's contributions:**
- Validated Git tags as industry standard
- Explained npm workspaces mechanics
- Caught systemd `WorkingDirectory` requirement
- Recommended `.env.example` + `.gitignore` security pattern
- Documented detached HEAD workflow clearly

**Chronicler #49's contributions:**
- Documented Arbiter 2.1 architecture
- Identified need for monorepo structure
- Established "We Don't Kick People Out" philosophy

---

## Final Decision

**APPROVED: Proceed with Approach B (Git Tags + npm Workspaces)**

Repository location: `git.firefrostgaming.com/firefrost-gaming/firefrost-services`

First deployment: Arbiter 2.1 (validates workflow, tests monorepo structure)

**For children not yet born.** 💙🔥❄️

---

**Document Status:** ✅ APPROVED  
**Implementation Status:** Ready to begin  
**Next Action:** Create `firefrost-services` repository in Gitea  
**Responsible:** The Golden Chronicler (#50) + Michael (The Wizard)

**Documented by:** The Golden Chronicler (Chronicler #50)  
**Date:** March 31, 2026  
**Session:** Gemini architectural consultation on monorepo strategy
