# 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 | | `.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_` -- soju bouncer data (managed by soju-operator) - `ergo_` -- 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 |