> ## Documentation Index
> Fetch the complete documentation index at: https://docs.equa.cc/llms.txt
> Use this file to discover all available pages before exploring further.

# Deployment Infrastructure

> Deployment history, current infrastructure, Docker configs, DNS, SSL, local development setup, and future deployment targets

# Deployment Infrastructure

> **Last verified:** 2026-05-03 | **Committed routing sources:** `equa-web/nginx.conf`, `equa-web/Dockerfile`, `equa-web/webpack.config.js`, `equa-web/.github/workflows/equa-cc-domain-smoke.yml` | **Legacy deployment source:** `equa-server/cloudbuild.yaml` | **Live edge capture:** `2026-05-03T16:09:41Z` against `equa-web` commit `3131f1699ae9df3dcf3655611bc8fb247afbb33e`

***

## Deployment History Timeline

```mermaid theme={null}
timeline
    title Equa Platform Deployment History
    section AWS Era
        AWS Deployment : EC2/ECS, S3, SES, RDS
                       : Full production stack
                       : Details in Google Drive/Confluence (audit pending)
    section GCP Era
        Google Cloud Run : equa-backend service
                        : Managed PostgreSQL (likely Cloud SQL; provider under audit)
                        : HTTPS Load Balancer
                        : Static IP 136.110.187.76
    section Wind-Down
        Feb 16, 2026 : Decision to wind down equa.cc
                     : Save $300-500/mo in hosting costs
                     : No paying customers yet
    section Future
        TBD : Local-first development focus
            : Mac/iOS Desktop App first
            : Re-deploy to production when ready
```

### Era 1: AWS (Prior Deployment)

<Warning>
  **Unconfirmed — Requires Google Drive/Confluence Audit**

  The Equa platform was previously deployed on AWS. Evidence of AWS services that remain active in the codebase:

  * **AWS S3** — File storage via `aws-sdk/clients/s3` in `equa-server/modules/file-storage/src/s3.d.ts`
  * **AWS SES** — Email sending via `equa-server/modules/notifications/src/nodemailer/email-notifier.ts`

  The full AWS deployment architecture (compute service, database, networking, and migration details) is documented in Google Drive and Confluence but has not yet been audited or exported locally. This section will be completed after that audit.

  **Items to confirm:**

  * Compute: EC2, ECS, Elastic Beanstalk, or Lambda?
  * Database: RDS PostgreSQL instance details
  * Networking: VPC, load balancer, SSL certs
  * Migration timeline: When and why moved to GCP
</Warning>

### Era 2: GCP Cloud Run / Public Cloud Legacy

The GCP-era public deployment still exists in repository automation. `equa-server/cloudbuild.yaml` deploys `equa-backend` to Cloud Run in `us-central1` on port `3000`, which remains relevant for cost wind-down and legacy endpoint investigations. It is no longer the authoritative browser-routing story for the SPA host.

**Source:** `equa-server/cloudbuild.yaml`, Lines: 13-46

### Era 3: Railway Interim / Local-First

The current committed interim routing story lives in `equa-web/nginx.conf`: `equa.cc` and `www.equa.cc` return `301` to `https://app.equa.cc$request_uri`, the default server block accepts the active SPA host, and `/api/` proxies to `https://equa-server-so-production.up.railway.app/`. The container defaults `PORT=8080` and exposes `8080`, so Railway target-port parity remains the first check if the edge regresses to `502`.

**Sources:**

* `equa-web/nginx.conf`, Lines: 4-29
* `equa-web/Dockerfile`, Lines: 44-49

### Era 4: Spec 040 Target

Spec 040 still targets `equa.cc` as the canonical marketing + app hostname with `app.equa.cc` eventually redirecting back to apex. Treat that as target-state planning, not as a claim about the live edge today.

**Source:** `command-center-so/specs/040-equa-cc-landing-rebuild/spec.md`, Section: 3.1

***

## Routing Truth Layers

### Committed\_interim

As committed today, `equa-web` defines two nginx server blocks. One block catches `equa.cc` and `www.equa.cc` and issues a `301` to `https://app.equa.cc$request_uri`; the other block serves the SPA, proxies `/api/` to `https://equa-server-so-production.up.railway.app/`, and inherits `${PORT}` from the runtime environment. This is the authoritative routing story for documentation until the repo changes.

**Sources:**

* `equa-web/nginx.conf`, Lines: 4-29
* `equa-web/Dockerfile`, Lines: 44-49

### Live\_edge\_baseline

The live edge must be treated as a separate measurement layer. The following snapshot was captured at `2026-05-03T16:09:41Z` against `equa-web` commit `3131f1699ae9df3dcf3655611bc8fb247afbb33e`; re-run it before any DNS, OAuth, or cutover decision.

| Probe                                     | Observed result                                                                           | Why it matters                                                                                                                                |
| ----------------------------------------- | ----------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `https://equa.cc/`                        | `HTTP/2 301` to `https://app.equa.cc:443/`, then `HTTP/2 200` with `server: railway-edge` | Apex live behavior now follows the committed interim redirect intent and reaches the app host.                                                |
| `dig equa.cc @8.8.8.8`                    | `A 136.110.187.76`                                                                        | Apex DNS still resolves to the legacy Google-era address before redirecting to the Railway-backed app host.                                   |
| `https://www.equa.cc/`                    | `HTTP/2 301` to `https://app.equa.cc:443/`, then `HTTP/2 200` with `server: railway-edge` | `www` now resolves and follows the same redirect path as apex.                                                                                |
| `dig www.equa.cc @8.8.8.8`                | `A 136.110.187.76`                                                                        | `www` is no longer NXDOMAIN, but still uses the legacy Google-era A record before redirect.                                                   |
| `https://app.equa.cc/`                    | `HTTP/2 200` with `server: railway-edge` and Fastly cache headers                         | The app host reaches Railway and serves the SPA shell.                                                                                        |
| `dig app.equa.cc @8.8.8.8`                | `CNAME ry6le6wy.up.railway.app.` → `151.101.2.15`                                         | `app.equa.cc` is the Railway-backed live host today.                                                                                          |
| `https://app.equa.cc/api/v1/user/current` | `HTTP 200`, body `{}`                                                                     | Same-origin API traffic reaches the Railway-backed API route; this validates the browser path shape, not authenticated application semantics. |
| `https://api.equa.cc/`                    | `HTTP/2 404` with `via: 1.1 google`                                                       | The direct API host remains legacy/unverified; browser documentation should prefer same-origin `https://app.equa.cc/api/v1`.                  |

Use this table to distinguish live behavior from committed intent. The runbook explains how to refresh each row and how to prepend `captured_at` plus `equa_web_commit` headers when pasting evidence into a PR or ticket.

**Source:** `equa-web/specs/037-docs-deploy-truth/VALIDATION-RUNBOOK.md`, Sections: 1-5

### Legacy\_GCP\_notes

The repository still contains the previous Cloud Run deploy path for `equa-backend`. Keep that material for cost, rollback, and historical architecture context only. Do not describe Cloud Run as the sole current browser/API path unless a direct endpoint is re-verified and explicitly labeled as an alternate endpoint.

**Source:** `equa-server/cloudbuild.yaml`, Lines: 13-46

### Target\_Spec040

Spec 040 is still the cutover target: the marketing site and authenticated SPA converge on canonical `equa.cc`, and `app.equa.cc` becomes the redirect. That plan remains separate from the interim nginx story and separate from the live-edge baseline above.

**Source:** `command-center-so/specs/040-equa-cc-landing-rebuild/spec.md`, Section: 3.1

### Verifying Edge Behavior

For operator captures, use the read-only validation runbook in `equa-web` rather than copying shell snippets out of this page. GitHub permalink: [Spec 037 validation runbook](https://github.com/EQUAStart/equa-web/blob/3131f1699ae9df3dcf3655611bc8fb247afbb33e/specs/037-docs-deploy-truth/VALIDATION-RUNBOOK.md)

## Legacy GCP Cloud Run Reference

### Cloud Build Pipeline

**Source:** `equa-server/cloudbuild.yaml`

```yaml theme={null}
steps:
  # 1. Build Docker image
  - name: 'gcr.io/cloud-builders/docker'
    args: ['build', '-t', 'gcr.io/$PROJECT_ID/equa-backend:$COMMIT_SHA', '.']

  # 2. Push to Google Container Registry
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/$PROJECT_ID/equa-backend:$COMMIT_SHA']

  # 3. Deploy to Cloud Run
  - name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
    entrypoint: gcloud
    args: ['run', 'deploy', 'equa-backend', ...]
```

### Cloud Run Service Configuration

| Property      | Value                                         | Source                        |
| ------------- | --------------------------------------------- | ----------------------------- |
| Service name  | `equa-backend`                                | `cloudbuild.yaml` line 19     |
| Region        | `us-central1`                                 | `cloudbuild.yaml` line 23     |
| Image         | `gcr.io/$PROJECT_ID/equa-backend:$COMMIT_SHA` | `cloudbuild.yaml` line 7      |
| Port          | `3000`                                        | `cloudbuild.yaml` line 29     |
| Memory        | `1Gi`                                         | `cloudbuild.yaml` line 30     |
| CPU           | `1`                                           | `cloudbuild.yaml` line 31     |
| Min instances | `1`                                           | `cloudbuild.yaml` line 32     |
| Max instances | `10`                                          | `cloudbuild.yaml` line 33     |
| Timeout       | `300s`                                        | `cloudbuild.yaml` line 34     |
| Access        | `--allow-unauthenticated`                     | `cloudbuild.yaml` line 27     |
| Features      | Startup CPU boost, CPU throttling             | `cloudbuild.yaml` lines 39-40 |
| Logging       | `CLOUD_LOGGING_ONLY`                          | `cloudbuild.yaml` line 46     |

<Warning>
  **Unconfirmed — Requires GCP Console Access**

  * GCP Project ID (`$PROJECT_ID` in cloudbuild.yaml)
  * Cloud SQL instance details (type, tier, version, connection method)
  * Load balancer name and configuration specifics
  * Static IP reservation details
  * Monthly cost breakdown by SKU

  The GCP cost check runbook at `stacks-ranking-priorities/runbooks/EQUA_CC_COST_CHECK.md` identifies Cloud SQL as the #1 cost driver.
</Warning>

***

## Docker Configurations

### Backend: equa-server

**Source:** `equa-server/Dockerfile`

| Stage      | Base Image       | Purpose                                                                                                              |
| ---------- | ---------------- | -------------------------------------------------------------------------------------------------------------------- |
| Build      | `node:18-alpine` | Install deps (`yarn install --frozen-lockfile`), compile TypeScript (`tsc --build` for file-storage and api modules) |
| Production | `node:18-alpine` | PM2 runtime, health check, production serving                                                                        |

**Build dependencies:** git, python3, make, g++ (for native npm module compilation)

**Process manager:** PM2 v5 (`pm2-runtime start ecosystem.config.js --only api`)

**Health check:** `wget --spider http://localhost:3000/` every 30s (3s timeout, 5s start period, 3 retries)

**Environment variables:**

| Variable            | Default      | Purpose                                                                       |
| ------------------- | ------------ | ----------------------------------------------------------------------------- |
| `PORT`              | `3000`       | HTTP listen port                                                              |
| `NODE_ENV`          | `production` | Node environment                                                              |
| `DATABASE_TYPE`     | `postgres`   | Database driver                                                               |
| `DATABASE_HOST`     | —            | PostgreSQL host                                                               |
| `DATABASE_USERNAME` | —            | Database user                                                                 |
| `DATABASE_PASSWORD` | —            | Database password                                                             |
| `DATABASE_NAME`     | —            | Database name                                                                 |
| `API_SSL`           | —            | Enable HTTPS (loads certs from `SSL_PRIVATE_KEY_PATH`, `SSL_PUBLIC_KEY_PATH`) |

**Source:** `equa-server/Dockerfile` (full file), `equa-server/README.md` (database env vars), `equa-server/modules/api/src/server.ts` lines 53-97 (SSL and port config).

### Frontend: equa-web

**Source:** `equa-web/Dockerfile`

| Stage      | Base Image       | Purpose                                        |
| ---------- | ---------------- | ---------------------------------------------- |
| Build      | `node:20-alpine` | Install deps, run webpack production build     |
| Production | `nginx:alpine`   | Serve static files, reverse proxy API requests |

**Build settings:**

* `NODE_OPTIONS=--openssl-legacy-provider` (required for older webpack/SSL compatibility)
* `API_URL=/api/v1` (baked into the build)
* Webpack runs via `npx webpack --mode production` (changed from direct `node_modules/.bin/webpack` in PR #501)
* A post-install verification step checks for the webpack binary and fails fast with a clear error if missing

**Required environment variables for build:**

| Variable              | Purpose                                                        | Source              |
| --------------------- | -------------------------------------------------------------- | ------------------- |
| `GH_PATTERNLIB_TOKEN` | GitHub token for fetching `equa-patternlib` private dependency | PR #501             |
| `API_URL`             | Backend API base URL (default: `/api/v1`)                      | `webpack.config.js` |

<Warning>
  The build **requires** `GH_PATTERNLIB_TOKEN` to be set as a Railway service variable. Without it, `yarn install` silently fails to fetch `equa-patternlib` (SSH clone fails on Alpine), leaving `node_modules` corrupt. PR #501 added a verification step that catches this early.
</Warning>

**Nginx configuration** (`equa-web/nginx.conf`):

| Feature       | Configuration                                                                                                     |
| ------------- | ----------------------------------------------------------------------------------------------------------------- |
| Listen port   | `${PORT}` (templated via envsubst at container startup; Dockerfile `ENV PORT=8080` provides the fallback)         |
| Apex redirect | `equa.cc` and `www.equa.cc` return `301` to `https://app.equa.cc$request_uri` when this config is the active edge |
| API proxy     | `/api/` → `https://equa-server-so-production.up.railway.app/`                                                     |
| Static files  | `/usr/share/nginx/html` with 1-year cache (`Cache-Control: public, immutable`)                                    |
| SPA fallback  | All routes serve `index.html`                                                                                     |
| Gzip          | Enabled for text, CSS, JSON, JS, XML                                                                              |
| Health check  | `GET /health` returns `200 OK`                                                                                    |

**Dynamic PORT (PR #516):** Prior to 2026-04-02, `nginx.conf` hard-coded `listen 8080`. Railway injects a `$PORT` env var per service instance and the hard-coded value worked only because it happened to match the Dockerfile `EXPOSE`. PR #516 changed the config to `listen ${PORT}` and runs `envsubst` on the template before `nginx` starts, so the container honours whatever port Railway assigns. Local `docker run` still defaults to `8080` via the Dockerfile `ENV PORT=8080`.

**Source:** `equa-web/Dockerfile` (full file), `equa-web/nginx.conf` (full file), PR #516 (2026-04-02).

***

## Railway Deployments

Four services have Railway deployment configurations:

### equa-server (Railway)

**Source:** `equa-server/railway.toml`

| Property       | Value                       |
| -------------- | --------------------------- |
| Builder        | nixpacks                    |
| Start command  | `npm run start:api`         |
| Health check   | `/health` (timeout: 300s)   |
| Restart policy | on\_failure (max 3 retries) |

### equa-web (Railway)

**Source:** `equa-web/railway.toml`

| Property       | Value                       |
| -------------- | --------------------------- |
| Builder        | nixpacks                    |
| Start command  | `npm run start`             |
| Health check   | `/` (timeout: 100ms)        |
| Restart policy | on\_failure (max 3 retries) |

### equa-patternlib (Railway — Storybook)

**Source:** `equa-patternlib-nextjs/railway.toml`

| Property       | Value                                       |
| -------------- | ------------------------------------------- |
| Builder        | nixpacks                                    |
| Build command  | `npm run build-storybook`                   |
| Start command  | `npx http-server storybook-static -p $PORT` |
| Health check   | `/` (timeout: 100ms)                        |
| Restart policy | on\_failure (max 3 retries)                 |

### Command Center (Railway)

**Source:** `command-center-so/railway.toml`

| Property          | Value                                                                                                 |
| ----------------- | ----------------------------------------------------------------------------------------------------- |
| Builder           | nixpacks                                                                                              |
| Start command     | `npm run start`                                                                                       |
| Health check      | `/command-center/api/health` (timeout: 100ms)                                                         |
| Restart policy    | on\_failure (max 3 retries)                                                                           |
| Required env vars | `EQUABOT_GATEWAY_URL`, `EQUABOT_GATEWAY_TOKEN`, `AUTH_SECRET`, `AUTH_GOOGLE_ID`, `AUTH_GOOGLE_SECRET` |

***

## DNS and Networking

### Host-by-Host Baseline

| Host          | Committed intent                                      | Live edge on 2026-05-03                                                           | Status                                                                                                  |
| ------------- | ----------------------------------------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
| `equa.cc`     | `301` to `https://app.equa.cc$request_uri`            | `HTTP/2 301` to `https://app.equa.cc:443/`, then `HTTP/2 200`; `A 136.110.187.76` | Live apex now redirects to the app host, while DNS still lands on the legacy Google-era A record first. |
| `www.equa.cc` | Same `301` as apex when attached to the nginx service | `HTTP/2 301` to `https://app.equa.cc:443/`, then `HTTP/2 200`; `A 136.110.187.76` | `www` now resolves and follows the same redirect path as apex.                                          |
| `app.equa.cc` | Active SPA host served by the default nginx block     | `HTTP/2 200`, `CNAME ry6le6wy.up.railway.app.` → `151.101.2.15`                   | Railway-backed SPA host is serving.                                                                     |

<Note>
  `www.equa.cc` was intentionally a soft check in the automated smoke workflow while DNS was missing. As of the 2026-05-03T16:09:41Z capture, it resolves and redirects successfully; keep the soft-check behavior until the cutover contract is explicitly tightened.

  Source: `equa-web/.github/workflows/equa-cc-domain-smoke.yml`, Lines: 31-46
</Note>

### Reverse Proxy (Nginx)

In the committed interim config, `equa-web`'s nginx container handles both host redirect behavior and the same-origin API path:

```
equa.cc, www.equa.cc  →  301 https://app.equa.cc$request_uri
/api/*                 →  https://equa-server-so-production.up.railway.app/
```

Headers set on the backend hop: `Host` (`equa-server-so-production.up.railway.app`), `X-Real-IP`, `X-Forwarded-For`, `X-Forwarded-Proto`.

**Source:** `equa-web/nginx.conf`, Lines: 4-29

***

## AWS Services (Active in Codebase)

### S3 File Storage

The file-storage module uses the AWS SDK v2 for S3 operations:

| Function                                          | Purpose                       | Source                             |
| ------------------------------------------------- | ----------------------------- | ---------------------------------- |
| `newS3Client(config)`                             | Create S3 client from config  | `modules/file-storage/src/s3.d.ts` |
| `uploadS3(s3, bucket, stream, file, contentType)` | Upload file to bucket         | `modules/file-storage/src/s3.d.ts` |
| `downloadS3(s3, bucket)`                          | Download file from bucket     | `modules/file-storage/src/s3.d.ts` |
| `newS3FileUploader(s3, bucket)`                   | Create file uploader instance | `modules/file-storage/src/s3.d.ts` |

Configuration via `AwsFileStorageConfig` (env vars — bucket name, region, access key, secret key).

<Warning>
  **Unconfirmed:** S3 bucket name, region, and whether this is the same AWS account as the prior full AWS deployment.
</Warning>

### SES Email

The notifications module uses AWS SES as the primary email transport with SMTP as fallback:

**Source:** `equa-server/modules/notifications/src/nodemailer/email-notifier.ts`

<Warning>
  **Unconfirmed:** SES region, verified sender domains/emails, and sending limits.
</Warning>

***

## Database Infrastructure

### PostgreSQL (Confirmed from Code)

| Property          | Value                                                           | Source                                                         |
| ----------------- | --------------------------------------------------------------- | -------------------------------------------------------------- |
| Database type     | PostgreSQL                                                      | `equa-server/README.md`                                        |
| ORM               | TypeORM 0.2.24                                                  | `equa-server/modules/persistence/package.json`                 |
| Entity count      | 92+ entities                                                    | `equa-server/modules/persistence/src/schema.ts` (\~2000 lines) |
| Schema definition | `equa-server/modules/persistence/src/schema.ts`                 | TypeORM entity classes                                         |
| Connection config | Environment variables                                           | `equa-server/README.md`                                        |
| Session storage   | TypeORM session store (express-session)                         | `equa-server/modules/api/src/server.ts` line 189               |
| Access pattern    | All modules use `persistence` helpers, not direct TypeORM calls | `equa-server/README.md` line 106                               |

**Connection environment variables:**

```
DATABASE_TYPE=postgres
DATABASE_HOST=localhost
DATABASE_USERNAME=postgres
DATABASE_PASSWORD=password
DATABASE_NAME=equa
DATABASE_LOGS=query,error      # optional
DATABASE_SCHEMA=               # optional
DATABASE_SYNC=                 # auto-sync in development
```

**Source:** `equa-server/README.md` lines 14-23.

### Production Database

<Warning>
  **Unconfirmed — Requires GCP Console Access**

  The production database is likely a managed PostgreSQL service, with Cloud SQL as the leading historical candidate, based on:

  * `stacks-ranking-priorities/runbooks/EQUA_CC_COST_CHECK.md` identifies Cloud SQL as the #1 cost driver
  * The wind-down runbook at `equabot/threads/wind-down-equa-cc-public-instance/WIND-DOWN-RUNBOOK.md` explicitly marks the database type as unknown ("Cloud SQL? Firestore? both?")

  **Items to confirm:**

  * Managed database provider, instance name, tier, and PostgreSQL version
  * Connection method (provider proxy, direct IP, Unix socket, or equivalent)
  * Backup configuration and retention
  * Storage size and IOPS
</Warning>

***

## SSL/TLS

### Cloud Run (Automatic)

Cloud Run provides automatic HTTPS with Google-managed SSL certificates for the service URL (`equa-server-333648330110.us-central1.run.app`).

### Custom Domains

<Warning>
  **Partially Verified**

  Public TLS termination is currently split by host. The 2026-05-03 baseline saw `equa.cc` reply through Google-managed infrastructure while `app.equa.cc` replied with Railway headers, so certificate ownership and edge termination must be re-verified per host before treating any DNS/HTTP prose as authoritative.
</Warning>

### Server-Side SSL (Optional)

The equa-server supports optional SSL termination at the application level:

| Env Var                | Purpose                         |
| ---------------------- | ------------------------------- |
| `API_SSL`              | Enable HTTPS server             |
| `SSL_PRIVATE_KEY_PATH` | Path to private key file        |
| `SSL_PUBLIC_KEY_PATH`  | Path to public certificate file |

When enabled, Express starts an HTTPS server instead of HTTP. This is typically not needed when running behind Cloud Run or a reverse proxy that handles TLS termination.

**Source:** `equa-server/modules/api/src/server.ts` lines 53-80.

***

## Local Development Setup

### Service Map

| Service           | Start Command                   | Port  | Directory                   |
| ----------------- | ------------------------------- | ----- | --------------------------- |
| PostgreSQL        | `docker run` (or local install) | 5432  | —                           |
| equa-server       | `yarn start:dev`                | 3000  | `equa-server/`              |
| equa-web          | `yarn dev`                      | 8080  | `equa-web/`                 |
| equa-patternlib   | `npm run storybook`             | 6006  | `equa-patternlib-nextjs/`   |
| command-center-so | `npm run dev`                   | 3001  | `command-center-so/`        |
| equabot-gateway   | `equabot gateway start`         | 18789 | `equabot/` (workspace root) |
| Ollama            | System service                  | 11434 | —                           |

### Proxy Configuration (Development)

In development, the Webpack dev server handles API proxying:

| Path            | Target                                |
| --------------- | ------------------------------------- |
| `/api`          | `http://localhost:3000` (equa-server) |
| `/equanaut-api` | `http://localhost:19792`              |

**Source:** `equa-web/webpack.config.js` (dev server proxy configuration).

### Prerequisites

1. **Node.js 18+** for `equa-web` / `equa-server`; **Node 22+** for `equabot-gateway` (see [Developer Setup](/onboarding/developer-setup) for per-repo version table)
2. **Yarn** (equa-server and equa-web use Yarn workspaces)
3. **npm** (command-center-so, equa-patternlib use npm)
4. **PostgreSQL** (local or Docker: `docker run -e POSTGRES_PASSWORD=password -p 5432:5432 postgres`)
5. **Git** (all repos cloned to `/Users/shawnowen/Documents/repos/`)

### Setup Steps

```bash theme={null}
# 1. equa-server
cd equa-server
cp .env.example .env  # configure DATABASE_* vars
yarn install
yarn tsc
yarn init:db          # if fresh database
yarn start:dev

# 2. equa-web
cd equa-web
yarn install
yarn dev              # serves on :8080, proxies /api to :3000

# 3. command-center-so
cd command-center-so
npm install
npm run dev           # serves on :3001

# 4. equa-patternlib (optional, for component development)
cd equa-patternlib-nextjs
npm install
npm run storybook     # serves on :6006
```

**Source:** `equa-server/README.md`, `equa-web/package.json` scripts, `command-center-so/package.json` scripts.

***

## Health Endpoints

| Service           | Endpoint                         | Response                                    |
| ----------------- | -------------------------------- | ------------------------------------------- |
| equa-server       | `GET /health`                    | `{"status": "healthy", "timestamp": "..."}` |
| equa-server       | `GET /`                          | `{"message": "API is running"}`             |
| equa-web (Nginx)  | `GET /health`                    | `200 OK` (text/plain)                       |
| command-center-so | `GET /command-center/api/health` | Health status JSON                          |

**Source:** `equa-server/modules/api/src/server.ts` lines 110-117, `equa-web/nginx.conf`, Lines: 54-58

***

## Wind-Down Status

### Decision Context

| Item          | Detail                                                                         |
| ------------- | ------------------------------------------------------------------------------ |
| Decision date | February 16, 2026                                                              |
| Reason        | Save \$300-500/month; no paying customers                                      |
| Strategy      | Local-first development focus                                                  |
| Reversibility | Full — all data backed up, infrastructure documented                           |
| GitHub issue  | [#358](https://github.com/Balancing-Rock/stacks-ranking-priorities/issues/358) |

### Redeployment Triggers

1. Feature-complete local version (Mac/iOS desktop app)
2. Paying customer pipeline ready
3. Funding available for hosting
4. Hosting platform decision finalized (GCP vs Railway vs other)

### Wind-Down Runbook

A detailed runbook exists at `equabot/threads/wind-down-equa-cc-public-instance/WIND-DOWN-RUNBOOK.md` covering:

* Pre-flight scope confirmation
* Inventory of all billable GCP resources
* Database and config backups/exports
* Traffic cutover and service scaling
* Cost verification

### Cost Analysis

The cost check runbook at `stacks-ranking-priorities/runbooks/EQUA_CC_COST_CHECK.md` identifies common lingering charge sources:

* **Cloud SQL** (often #1 cost driver)
* **Cloud Load Balancing** (forwarding rules, URL maps, proxies)
* **Cloud NAT** (if used)
* **Compute Engine** (disks, snapshots)
* **Artifact Registry** storage
* **Cloud Logging** ingestion/retention

***

## Appendix: Unconfirmed Items Requiring Audit

The following items cannot be verified from source code alone and require access to external systems. Use the [Phase 1 Audit Runbook](/architecture/phase1-audit-runbook) for step-by-step instructions to complete these audits and then update this document.

### Google Drive / Confluence Audit Required

| Item                                         | Expected Source                  |
| -------------------------------------------- | -------------------------------- |
| Full AWS deployment architecture (prior era) | Google Drive infrastructure docs |
| AWS → GCP migration timeline and rationale   | Confluence                       |
| Original AWS infrastructure diagrams         | Google Drive                     |
| Database migration records                   | Confluence                       |

### GCP Console Access Required

| Item                                | How to Verify                                                             |
| ----------------------------------- | ------------------------------------------------------------------------- |
| GCP project ID                      | GCP Console → Project selector                                            |
| Managed PostgreSQL provider details | Verify the live provider first, then inspect the matching console/service |
| Load balancer configuration         | GCP Console → Network Services → Load Balancing                           |
| Static IP reservation               | GCP Console → VPC Network → External IP Addresses                         |
| SSL certificate names               | GCP Console → Security → Certificate Manager                              |
| Monthly cost by SKU                 | GCP Console → Billing → Reports (last 30 days)                            |
| Nameserver configuration            | GCP Console → Cloud DNS → Zone details                                    |

### AWS Console Access Required

| Item                            | How to Verify                           |
| ------------------------------- | --------------------------------------- |
| S3 bucket name and region       | AWS Console → S3 → Buckets              |
| SES verified domains/emails     | AWS Console → SES → Verified Identities |
| SES sending region              | AWS Console → SES → Account Dashboard   |
| IAM user/role for S3+SES access | AWS Console → IAM                       |

Once these audits are complete, the "Unconfirmed" sections in this document should be updated with verified details and the warning boxes removed.

***

## Deployment Checklist

> **Source:** Confluence KnowledgeBase — [Deployment Checklist](https://equa.atlassian.net/wiki/spaces/KNOWLEDGEB/pages/334299576/Deployment+Checklist) (by Christopher Johnson, v2.27.0)

### Standard Deployment Procedure

1. [ ] Pull code
2. [ ] Bump versions
3. [ ] Push frontend staging code
4. [ ] Push backend staging code
5. [ ] Notify team that deployment has started
6. [ ] Push frontend production code
7. [ ] Push backend production code
8. [ ] Restart backend server
9. [ ] Migrate database
10. [ ] Watch for frontend to finish deploying
11. [ ] Check production site
12. [ ] Notify team that deployment is finished

### Pre-Deploy Checks (supplementary)

* [ ] All tests passing on target branch
* [ ] Database migrations reviewed and tested on staging
* [ ] Environment variables verified for target environment
* [ ] Stakeholder sign-off obtained

### Post-Deploy Verification (supplementary)

* [ ] Health endpoint responds 200
* [ ] Login flow functional
* [ ] Key API endpoints return expected data
* [ ] No new error spikes in monitoring

### Rollback Procedure

* [ ] Identify the issue (logs, monitoring, user reports)
* [ ] Revert to previous Cloud Run revision or Railway deployment
* [ ] Verify rollback successful
* [ ] Investigate root cause before re-deploying
