# Guild settings module

## Responsibilities

- store raw per-guild settings in `guild_settings`
- convert DB rows to string-friendly objects for the API
- support the cached runtime view returned by `shared/lib/config.ts`

## Main methods

- `getSettings(guildId)`
- `upsertSettings({ guildId, ...fields })`
- `updateSetting(guildId, key, value)`
- `deleteSettings(guildId)`
- `addColorRole(guildId, roleId)`
- `removeColorRole(guildId, roleId)`

## Runtime cache

- `shared/lib/config.ts` caches `getGuildConfig()` results for 60 seconds
- API writes invalidate that cache immediately
- the cached runtime shape is not identical to the DB shape:
  - `studentRoleId` -> `studentRole`
  - `visitorRoleId` -> `visitorRole`
  - `colorRoleIds` -> `colorRoles`
  - terminal fields are grouped under `terminal`

## Notes

- `updateSetting()` accepts friendly keys like `studentRole`, `welcomeChannel`, and `terminalMessage`
- Discord IDs are stored as `bigint` in the DB and exposed as strings from the service
- `addColorRole()` and `removeColorRole()` read-modify-write the whole array, so they are not atomic under concurrent updates
