# Helix

Unified IT platform for people, accounts, permissions, assets, and workflows. Built for a ~500-person organization.

Start here for the current state and roadmap:
- [ROADMAP.md](ROADMAP.md)

## Architecture

```
helix/
├── server/          # FastAPI backend (Python 3.12)
├── web/             # React 19 frontend (TypeScript + Vite 7 + Ant Design 6)
├── infra/           # Terraform — AWS infrastructure & TiDB Cloud
├── deploy/          # Docker Compose prod config & deploy scripts
├── .github/         # GitHub Actions CI/CD workflows
├── scripts/         # Sync & import utilities
└── docker-compose.yml  # Local dev (Redis)
```

**Backend**: FastAPI + SQLAlchemy 2.0 async + TiDB/MySQL + Redis 7
**Frontend**: React 19 + TypeScript 5.9 + Vite 7 + Ant Design 6 + antd-mobile 5 + Zustand
**Auth**: Google SSO -> JWT, identity sourced from SuccessFactors
**RBAC**: canonical roles are `global_admin`, `employee`, `auditor`, `asset_admin`, `cloud_admin`, `hr`, `finance`, `management` (plus manager scope derived from `manager_person_id`)

## Modules

For an up-to-date module catalog (foundation, identity/HR, asset, software seats, API keys, provisioning, offboarding + Leaver Blocked, cloud lifecycle across 8 providers, security auditor, AI spending, etc.) and what's currently in flight, see [ROADMAP.md](ROADMAP.md). For the architectural reference (every domain, table, scheduled job, driver), see [docs/architecture/PLATFORM.md](docs/architecture/PLATFORM.md).

## Quick Start (Local Development)

### Prerequisites

- Python 3.12+ with [uv](https://docs.astral.sh/uv/)
- Node.js 20+ with pnpm
- Docker (for Redis)
- Local MySQL/TiDB-compatible database

### 1. Environment

```bash
cp .env.example .env
# Edit .env with your credentials
```

### 2. Infrastructure

```bash
# Start Redis and, when needed, local MySQL
docker compose up -d

# If port 3306 is already occupied, override the published MySQL port:
# MYSQL_PORT=3307 docker compose up -d mysql redis
```

### 3. Backend

```bash
cd server
uv sync
uv run alembic upgrade head
uv run uvicorn app.main:app --reload --port 8000
```

### 4. Frontend

```bash
cd web
pnpm install
pnpm dev    # http://localhost:3000, proxies /api/v1 → :8000
```

### 5. Tests

```bash
cd server
uv run pytest
```

If your application database user cannot create `helix_test`, set `TEST_DATABASE_ADMIN_URL`
or point `TEST_DATABASE_URL` / `TEST_DATABASE_URL_SYNC` at a pre-created test database before
running `pytest`.

## Key Integrations

- **Google SSO**: Frontend `@react-oauth/google` → backend token verification
- **SuccessFactors**: OData API for people & org data
- **Feishu**: Approval workflows + chat notifications (chat_approval driver shipped)
- **Cloud (8 providers)**: AWS, Azure, GCP, Aliyun (RD + Intl), Tencent, UCloud, KSyun
- **Software seats**: Google Workspace, Slack, Zoom, Jira, GitHub, Feishu, manual

## Deployment

### Current: AWS EC2 + Docker Compose

- **CI/CD**: GitHub Actions (OIDC → AWS, no long-term keys)
- **Runtime**: EC2 instance running Docker Compose (backend, worker, frontend-nginx)
- **Database**: TiDB Cloud Dedicated (ap-southeast-1, PrivateLink)
- **Cache**: Amazon ElastiCache Redis
- **Load Balancer**: AWS ALB with ACM TLS termination
- **Secrets**: AWS SSM Parameter Store
- **Images**: Amazon ECR (helix-server, helix-web, helix-worker)

Pushes to `main` automatically build and publish the immutable release images:
1. `ci.yml` validates backend, frontend, and Docker smoke builds
2. `image-release.yml` starts only after `ci.yml` succeeds, then builds and pushes `sha-<commit>` and `main` tags to ECR

Production deployment is deliberately manual: after the reviewed `main` image
exists, run `Production Deploy` with its exact `sha-<full-commit>` tag and
matching `git_ref`. The reusable `deploy-ec2.yml` workflow then syncs deploy
assets to EC2 and rolls the host forward via SSM. This separation keeps image
publication from becoming an implicit production mutation.

See [docs/deployment/](docs/deployment/) for full deployment guide.

### Future: Kubernetes (EKS)

The current architecture is designed for future migration to EKS:
- Container images are already built and stored in ECR
- Application is stateless — horizontal scaling requires only orchestrator change
- Secrets are in SSM/Secrets Manager — compatible with ExternalSecrets operator
- ALB can be replaced with AWS Load Balancer Controller

## CLI

The official `helix` CLI is a thin client over the existing MCP Streamable-HTTP server. It reuses Helix Personal Access Tokens (the same `helix_pat_…` tokens already used by Claude Desktop / Cursor / CI scripts) so there is no second login flow, no service account, and no PAT scope expansion. The CLI inherits whatever permissions the token's owner has in the web UI; mutating commands flow through the same approval / RBAC / audit chain as a UI click.

### Install

The CLI is its own dependency-light distribution at repo-root [`cli/`](cli/) (package `helix_cli`, only depends on `httpx`) — it does **not** require the backend. For local development:

```bash
cd cli
pip install -e .        # registers the `helix` console-script
helix --help
python -m helix_cli --help   # equivalent module entrypoint
```

End users (employees) don't install from source: the release pipeline publishes a `pip`/`pipx`-installable wheel and per-OS single-file binaries downloadable from the Helix web UI (Help → AI 助手集成 → helix CLI). See the help center for the self-service download + setup flow.

### First-time setup

PATs are still managed in the **web UI** (Settings → Personal Access Tokens) — the CLI deliberately does not implement PAT creation, since that would fork the auth-flow surface. After creating a PAT in the browser:

```bash
# Pipe the token in via stdin so it never lands in your shell history
# or in `ps(1)` output. There is no `--token` flag for this reason.
pbpaste | helix auth token set --token-stdin

# Point the CLI at your environment
helix config set-url https://helix.example.com

# Confirm
helix config show     # token only ever shown as "helix_pat_ab****"
```

For CI / scripts, set environment variables instead of writing to disk:

```bash
export HELIX_BASE_URL=https://helix.example.com
export HELIX_PAT=helix_pat_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
helix whoami --json
```

### Common commands

```bash
helix whoami                          # MCP: whoami
helix assets list                     # MCP: list_my_assets
helix software catalog                # MCP: list_software_catalog
helix software seats                  # MCP: list_my_software_seats
helix cloud servers                   # MCP: list_cloud_servers
helix notifications summary           # MCP: get_my_notifications_summary
helix notifications list              # MCP: list_my_notifications
helix approvals list                  # MCP: list_my_approval_requests
helix health                          # GET /api/v1/health (no auth)
helix ready                           # GET /api/v1/ready (no auth)

# Direct MCP access for any of the registered MCP tools (320+):
helix mcp tools
helix mcp call list_my_assets --arg page=1 --arg page_size=50
helix mcp call submit_approval_request --json-arg '{"template_id":"...","form":{...}}'

# Add --json to any command for machine-readable output.
```

### Security notes

- **Never write your PAT into shell history**: always pipe via `--token-stdin`, or use `HELIX_PAT`.
- The on-disk config (`~/.config/helix/config.json`, override with `HELIX_CONFIG`) is written `0o600`.
- `config show` only prints the redacted prefix (`helix_pat_ab****`); the full token is never logged.
- All CLI output passes through a redaction filter, including stack traces under `HELIX_DEBUG=1`.
- The CLI never auto-retries a failed call — important for mutating tools, where a retry would risk double-submitting an approval / ticket.

## Production Auth

Production environment enforces Google SSO only:
- Backend rejects password login when `AUTH_PASSWORD_LOGIN_ENABLED=false`
- Frontend hides password form in production
- Google OAuth uses production client ID and domain-restricted origins

## License

Private — internal use only.
