AGENTS.md 7.9 KB

AGENTS.md

Project overview

Open OSCAR Server is an open-source instant messaging server written in Go that is compatible with classic AIM and ICQ clients. It implements the OSCAR, TOC, and Kerberos protocols, plus HTTP management and web APIs. It is independent of AOL/Yahoo and non-commercial.

Quick commands

Task Command
Build go build -o open_oscar_server ./cmd/server
Test go test -race ./...
Lint (matches CI) gofmt -s -l . && go vet ./...
Run (dev, plain) make run
Run (dev, SSL) make run-ssl (+ make run-stunnel in a second terminal)
Generate config make config
Regenerate mocks mockery
Build Docker images make docker-images

Architecture

The binary in cmd/server starts five servers concurrently via errgroup:

Server Protocol Default port
OSCAR FLAP/BOS (binary) 5190 (5193 via stunnel for SSL)
TOC TOC (text-based) 9898
Kerberos Kerberos auth 1088
MgmtAPI HTTP (management) 8080
WebAPI HTTP (web AIM-style, AMF3) 9000 (opt-in via ENABLE_WEBAPI=1)

All five servers share a common dependency container (Container in cmd/server/factory.go) that wires together config, persistence, and business logic.

Key packages

Package Role
cmd/server Entry point; wires dependencies and starts all servers.
config Configuration via env vars (envconfig). Config files are generated from the Config struct—do not edit them by hand; run make config instead.
foodgroup Core business logic for OSCAR "food groups": Auth, Buddy, Feedbag, ICBM, Chat, BART, Locate, OService, ICQ, Admin, PermitDeny, ODir, Stats, UserLookup, ChatNav. Shared by the OSCAR, TOC, and WebAPI servers.
wire OSCAR wire protocol: SNAC/FLAP encoding, TLV, food group codes, rate limits, frames.
state Persistence and in-memory state: SQLiteUserStore, InMemorySessionManager, InMemoryChatSessionManager, DB migrations.
server/oscar OSCAR protocol server; SNAC routing and handler wiring.
server/toc TOC protocol server (text-based).
server/kerberos Kerberos auth server.
server/http Management HTTP API (users, sessions, chat rooms). Spec: api.yml.
server/webapi Web AIM-style API (AMF3). Spec: docs/open_api/webapi.yml.

Database

SQLite via modernc.org/sqlite (pure-Go, no CGO). Default file: oscar.sqlite. Migrations live in state/migrations/ as numbered .up.sql / .down.sql pairs and are applied automatically at startup.

Configuration

Configuration is env-var driven via kelseyhightower/envconfig. Settings files (config/settings.env, config/ssl/settings.env) are generated from the Config struct by running make config. Never edit them by hand—change the Config struct and regenerate.

Testing conventions

  • Table-driven tests — slices of structs with name, inputs, and expected outputs; iterated with t.Run.
  • Assertionsgithub.com/stretchr/testify/assert (assert.Equal, assert.NoError, etc.).
  • Mocks — generated by mockery (config in .mockery.yaml). Mock files are named mock_*_test.go and live next to the code they test. Regenerate with mockery at the repo root.
  • mockParams structs — group per-test-case mock expectations; defined in *_helpers_test.go files alongside the tests.
  • Test helpers — shared fixtures and builders live in *_helpers_test.go.

Code style

  • Standard Go conventions; CI enforces gofmt -s and go vet.
  • Small, focused interfaces for dependency injection and testability (e.g. SessionRetriever, FeedbagManager).
  • Doc comments on all exported symbols.
  • Errors follow the standard if err != nil pattern; sentinel errors and custom error types are used where appropriate.

OSCAR protocol reference

The OSCAR protocol specification covers roughly 80% of the protocol: FLAP framing, SNAC structure, and the major food groups (OSERVICE, BUDDY, ICBM, FEEDBAG, BART, LOCATE, PD, INVITE). The remaining ~20% (e.g. some ICQ-specific SNACs, chat, and lesser-used food groups) is not documented there and must be reverse-engineered from client behavior or other sources.

Useful docs

Document Path
Build & run docs/BUILD.md
Management API spec api.yml
Web API spec docs/open_api/webapi.yml
OSCAR protocol spec https://devinsmith.net/backups/OSCAR/
Client setup guides docs/CLIENT.md, docs/CLIENT_TIK.md, docs/CLIENT_ICQ.md
Docker guide docs/DOCKER.md
Platform guides docs/LINUX.md, docs/MACOS.md, docs/WINDOWS.md

Go guidelines

  • Injected dependencies are non-nil — Types that the server factory wires up receive dependency fields through their constructors; those fields are non-nil before the value is used. Call dep.Method() directly. Do not add if dep != nil guards around those calls; that implies an optional dependency and duplicates an invariant already enforced by construction. (Optional pointers, slices, maps, and values from external input still need normal nil/empty checks.)