# irc.now Platform Design

## Overview

irc.now is a hosted IRC services platform. Users sign up for a managed IRC bouncer
(soju), optionally host their own IRC network (ergo), and access supporting tools:
a web client, pastebin, image host, and bot management.

The platform spans 9 subdomains across 3 concerns: user-facing web properties,
Kubernetes operators for IRC infrastructure, and an account/billing layer.

## Subdomains

| Domain | Purpose | Type |
|--------|---------|------|
| `irc.now` | Landing page | Static site |
| `account.irc.now` | Account portal, billing, bot management | Axum service |
| `auth.irc.now` | Keycloak SSO | Keycloak instance |
| `chat.irc.now` | Web IRC client | Gamja (AGPL) |
| `txt.irc.now` | Pastebin | Axum service |
| `irc.pics` | Image hosting | Axum service |
| `status.irc.now` | Status page | Upptime on GitHub Pages |
| `<name>.irc.now` | Per-tenant IRC network | ergo via operator |
| (internal) | Per-tenant IRC bouncer | soju via operator |

## Codebase Structure

Single Rust workspace. Operators use kube.rs, web services use Axum. Shared code
in an internal `common` crate.

```
irc-now/
  Cargo.toml              # workspace root
  crates/
    common/               # shared types, auth middleware, DB pool, S3 client
    soju-operator/        # manages SojuBouncer CRs (existing design)
    ergo-operator/        # manages ErgoNetwork CRs
    web-api/              # account.irc.now portal + API
    web-paste/            # txt.irc.now pastebin
    web-pics/             # irc.pics image host
    web-landing/          # irc.now static landing page server
  deploy/
    keycloak/             # Keycloak deployment manifests
    upptime/              # Upptime config reference
    gamja/                # gamja deployment manifests
```

## Shared Infrastructure

### Keycloak (auth.irc.now)

- Dedicated instance on OCP
- Single realm `irc-now`
- OIDC clients for: account portal, chat, pastebin, pics
- User attributes: `plan` (free/pro), `stripe_customer_id`
- All Axum services validate tokens via OIDC middleware in `common`

### Database

- Single CNPG PostgreSQL cluster
- Separate databases per concern:
  - `keycloak` -- Keycloak's own storage
  - `accounts` -- portal, billing records, bot configs
  - `paste` -- txt.irc.now paste content
  - `pics` -- irc.pics metadata (S3 keys, uploader, timestamps)
- Per-tenant databases created by operators:
  - `soju_<tenant>` -- soju bouncer data (managed by soju-operator)
  - `ergo_<tenant>` -- ergo network data (managed by ergo-operator)

### Object Storage

- S3-compatible bucket for irc.pics image blobs
- `common` crate provides S3 client wrapper (aws-sdk-s3 or rust-s3)

### Shared Crate (common)

- OIDC token validation middleware for Axum
- Database pool setup (sqlx, PostgreSQL)
- S3 client wrapper
- Shared API error types and response formats
- User and tenant types

## Service Designs

### irc.now -- Landing Page

Already built as static HTML with the design system. Deploy as a lightweight
container (nginx or a small Axum static file server). Links to `/login` and
`/signup` redirect to `account.irc.now` which initiates Keycloak flows.

### account.irc.now -- Account Portal

Axum service. Primary user-facing application after login.

**Auth flow:** User clicks login/signup on landing page -> redirect to Keycloak
-> OIDC callback at account.irc.now -> session established.

**Features:**
- Dashboard: overview of bouncer status, network status, usage
- Bouncer management: create/configure soju instance (creates SojuBouncer CR)
- Network management: create/configure ergo instance (creates ErgoNetwork CR)
- Bot management: CRUD bot configs (name, networks, channels, behavior)
- Billing: Stripe Checkout for pro upgrade, Stripe Customer Portal for subscription management
- DNS/hostname settings for pro users (custom bouncer hostname)

**Kubernetes integration:** Service account token scoped to SojuBouncer,
ErgoNetwork, and IrcBot CRD verbs. Portal creates/updates/deletes CRs through
the Kubernetes API.

**Billing flow:** Stripe webhooks update Keycloak user attributes (plan tier)
and trigger operator reconciliation for resource changes (e.g., upgrading from
shared to dedicated bouncer).

### chat.irc.now -- Web Client

Gamja deployed as a container on OCP. AGPLv3 licensed.

- Configured to connect to the user's soju bouncer endpoint
- Sits behind Keycloak auth: user logs in, app resolves their bouncer endpoint
- CSS customization to match the irc.now design system (external stylesheet, not
  a source modification -- avoids AGPL derivative work concerns)
- Connection defaults pre-configured per user

### txt.irc.now -- Pastebin

Small Axum service.

- Anonymous pastes allowed (rate-limited by IP)
- Authenticated users get paste history and longer retention
- Content stored in PostgreSQL (not files)
- Short random ID URLs: `txt.irc.now/abc123`
- Syntax highlighting rendered client-side (highlight.js or similar)
- Configurable TTL: anonymous pastes expire after 30 days, authenticated pastes
  persist indefinitely
- Raw view endpoint: `txt.irc.now/abc123/raw`

### irc.pics -- Image Host

Axum service.

- Authenticated upload only (via portal or direct API with bearer token)
- Images stored in S3, metadata in PostgreSQL
- Short URL scheme: `irc.pics/abc123`
- Thumbnail generation on upload (resize to standard widths)
- Rate-limited anonymous viewing
- Content-type validation on upload (images only)
- Size limit per upload, storage quota per user (higher for pro)

### status.irc.now -- Status Page

Upptime running on GitHub Actions, hosted on GitHub Pages.

- CNAME `status.irc.now` to GitHub Pages
- Monitors: irc.now, account.irc.now, auth.irc.now, chat.irc.now,
  txt.irc.now, irc.pics
- Runs outside the OCP cluster -- stays up if the cluster goes down
- Incidents tracked as GitHub Issues
- MIT licensed

### soju-operator

Existing design (see `soju-operator/docs/plans/2026-03-03-soju-operator-design.md`).

Manages `SojuBouncer` CRDs. Reconciles into Deployment, ConfigMap, Service,
Route, Certificate, and per-tenant PostgreSQL database. Finalizer handles DB
cleanup on deletion. AGPLv3 soju binary is run unmodified -- operator is
independent code.

### ergo-operator

Same pattern as soju-operator. Manages `ErgoNetwork` CRDs.

**CRD: ErgoNetwork** (`irc.josie.cloud/v1alpha1`)

```yaml
apiVersion: irc.josie.cloud/v1alpha1
kind: ErgoNetwork
metadata:
  name: my-network
spec:
  hostname: my-network.irc.now
  networkName: "My Network"
  listeners:
    - address: ":6697"
      tls: true
    - address: ":6667"
      tls: false
  tls:
    issuerRef:
      name: letsencrypt-prod
      kind: ClusterIssuer
    dnsNames:
      - my-network.irc.now
  route:
    host: my-network.irc.now
  operCredentials:
    secretName: my-network-oper
  resources:
    requests:
      memory: "64Mi"
      cpu: "50m"
    limits:
      memory: "256Mi"
      cpu: "200m"
```

**Reconciliation:** Same lifecycle as soju-operator -- Certificate, ConfigMap
(ergo YAML config), Deployment, Service, Route. Per-tenant database for ergo's
datastore. Finalizer for DB cleanup.

MIT-licensed ergo has no source-sharing obligations.

### irc.bot -- Bot Management

Not a separate service. A feature within the account portal (account.irc.now).

Users define bot configs: name, networks to join, channels, behavior/scripts.
Bots run as containers managed by an `IrcBot` CRD (or as sidecar containers in
the user's existing deployments).

This is a later-phase feature. Start with bouncer and network hosting, add bot
management once the core platform is stable.

## Deployment

All services deploy to the existing OCP cluster via `oc builds`.

- Each workspace crate produces a container image (multi-stage Rust build)
- Gamja and Keycloak use upstream images
- Upptime runs on GitHub, no cluster resources needed
- OCP Routes handle per-subdomain TLS termination
- cert-manager handles certificate issuance

## Build Order

Phase 1 -- Foundation:
1. Workspace scaffolding and `common` crate
2. Keycloak deployment
3. soju-operator (existing plan)
4. Account portal (basic auth flow, bouncer management, Stripe)
5. Landing page deployment

Phase 2 -- Supporting services:
6. chat.irc.now (gamja deployment)
7. txt.irc.now (pastebin)
8. irc.pics (image host)
9. status.irc.now (Upptime setup)

Phase 3 -- Network hosting:
10. ergo-operator
11. Network management in account portal

Phase 4 -- Bots:
12. Bot management UI in account portal
13. IrcBot operator/CRD

## License Summary

| Component | License | Implication |
|-----------|---------|-------------|
| soju | AGPLv3 | Run unmodified, link to upstream source |
| gamja | AGPLv3 | Run unmodified, CSS theming only |
| ergo | MIT | No restrictions |
| Keycloak | Apache 2.0 | No restrictions |
| Upptime | MIT | No restrictions |
| All custom code | TBD | Your choice |
