Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
13 changes: 0 additions & 13 deletions .github/CONTRIBUTING.md

This file was deleted.

7 changes: 0 additions & 7 deletions .github/SUPPORT.md

This file was deleted.

16 changes: 0 additions & 16 deletions .github/workflows/verify-configs.yml

This file was deleted.

1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
/node_modules/
/config/
src/functions/scnx-integration.js
instrument.js
/.vscode/
/.idea/
6 changes: 5 additions & 1 deletion developer-docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ Start here if you want to add a new feature as a module:
- [**Slash commands**](./commands.md) - `config` / `run` / `subcommands` / `autocomplete`, registration, options.
- [**Database models**](./database-models.md) - Sequelize `Model.init` pattern, `models-dir`, accessing models from
events.
- [**Field-level encryption**](./field-encryption.md) - the secure-storage serialization layer: which columns are
protected and how to register a new sensitive field.
- [**Localization**](./localization.md) - adding strings to `locales/en.json` and using `localize()`.
- [**Nickname manager**](./nickname-manager.md) - the shared service for changing member nicknames without modules
fighting each other.

## Configuration schema

Expand All @@ -34,7 +38,7 @@ The string + embed format used in `allowEmbed` config fields. Canonical referenc

## Migration

- [**Migration**](./migration.md) - upgrading between major bot versions.
- [**Migration**](./migration.md) - writing database migrations so schema changes reach existing installs.

## Validation

Expand Down
19 changes: 7 additions & 12 deletions developer-docs/database-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,18 +65,13 @@ All standard Sequelize methods are available: `findOne`, `findAll`, `findOrCreat

## Migrations

The bot calls `sequelize.sync()` at startup, which creates missing tables and adds missing columns automatically. **It
does not modify or remove existing columns.** If you change a column's type, rename it, or drop it, you have two
options:

1. **Manual migration.** Use Sequelize's [umzug](https://github.com/sequelize/umzug) or write SQL by hand. Drop the
bot's table or run `ALTER TABLE` against your database.
2. **Bump the table name.** For breaking schema changes, rename `tableName` (e.g. `welcomer_User_v2`). The old table
stays in place for safety; you migrate data on the side.

For non-trivial migrations across versions, the bot exposes `module.exports.migrationStart()` / `migrationEnd()` from
`main.js` - call these around long-running migration code so SIGTERM/SIGINT defers shutdown until the migration
finishes.
The bot calls `sequelize.sync()` at startup, which creates missing **tables**. **It does not add columns to existing
tables, nor modify or remove existing columns.** So whenever you add, rename, change, or drop a field on an existing
model, ship a migration alongside it so existing installs pick up the schema change.

Migrations are file-based and run automatically on boot by an [Umzug](https://github.com/sequelize/umzug)-based runner -
you drop a file into your module's `migrations/` directory and the runner discovers it, applies it once, tracks it, and
backs up the affected tables first. See [migration.md](./migration.md) for the full guide.

## Associations

Expand Down
41 changes: 41 additions & 0 deletions developer-docs/field-encryption.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# Field-level encryption (secure storage)

As part of our ongoing security and privacy work, the bot has an additional layer of protection for
the most sensitive user data: field-level encryption. Selected database columns are encrypted at the
application level, so sensitive fields stay protected even when someone has direct database access
(for example, a technician reviewing a database for support or debugging). It is an extra safeguard
layered on top of the broader security posture.

## What it means for the open-source build

In this repository the feature ships as a thin serialization wrapper with a passthrough crypto stub:

- Self-hosted instances and the test suite run with no key and no configuration. Nothing to set up.
- The registered columns are declared `TEXT`. The hooks serialize their JSON and integer values into
that text on write and parse them back on read, so your model code keeps working with plain objects
and numbers.
- The actual encryption is injected only on the managed backend. You never need a key locally, and the
encryption is a safe no-op here.

The wrapper lives in `src/functions/secure-storage/`:

- `fields.js` lists every protected column (the source of truth for what is secured).
- `hooks.js` registers the serialization hooks on each model.
- `fieldCrypto.js` is the passthrough stub the managed backend replaces.

## Contributor rules

If you write or change a module:

- **Keep `TEXT` columns as `TEXT`.** The hooks serialize JSON and integers into them; changing the
type breaks reads and writes.
- **Adding a sensitive free-text or PII field?** Declare it `TEXT` and register it in
`src/functions/secure-storage/fields.js` with its type (`string`, `json`, or `int`). Serialization
then happens automatically and the encryption is a safe no-op locally.
- **Do not register columns used in `WHERE`, `ORDER`, indexes, unique constraints, or aggregates.**
Encrypting those would break lookups. IDs, foreign keys, enums, booleans, counters, timestamps, and
external resource references stay as they are.
- **You never need a key.** Encryption activates only on the managed backend.

We update the existing fields of community modules when this requirement changes, so you normally do
not have to touch anything unless you are adding a new sensitive field.
Loading
Loading