# Writing belongs to the core, not to Forums

2026-08-08. Ernest, on being told Blog would have to depend on Forums:

> "Blogs needs to be independent of forums. Everything is supposed to depend on
> system not on forum on the official modules. The reason is if someone just
> wanted to use Convoro just for Blogs or Downloads or Pages they can."

That is the promise
[the application model](2026-08-07-the-application-model.md) made, and Blog was
about to be the first thing to break it.

---

## What was actually coupled

Measured before moving anything, because the answer changed the size of the job:

```
modules declaring `forum`:  blog, moderation
PHP references to Modules\Forum from outside forum:  none
```

**Nothing outside the forum module uses a single Forum class.** The coupling is
entirely about which module's migrations *create* `topics` and `posts`. That is
a much smaller problem than it looked, and it means the fix is ownership rather
than rewriting.

## The split

- **System** owns `topics`, `posts` and `topic_reads` — the writing, the
  replies, and whether somebody has read them. These are what a *person does*,
  not what a forum is.
- **Forums** keeps `forums`, prefixes, tags and polls — the container, and the
  things that only make sense inside one.

The test for each table: would a Convoro with no forums at all still need it?
A blog entry has comments, and comments are posts, and read state applies to
them — so those three move. Nothing needs a prefix without a forum to put it in.

## 🚨 `forum_id` becomes nullable, and that is the point

A topic in a blogs-only install has no forum to belong to, and `forum_id` was
`NOT NULL`. That single column was the reason the previous day's design put
comment topics inside a real forum and then had to keep them out of that
forum's counters.

Nullable is simpler and truer: a topic either belongs to a forum or belongs to
an application, and `owner_type` already says which.

## 🚨 Moving migrations between modules replays them

Migrations are recorded against the module that owns them. Moving four files
from `forum` to `system` makes `system` look as though it never ran them —
and the next `migrate` replays them onto tables that already exist, failing on
the first `CREATE TABLE`, mid-upgrade, on a live site.

There is a precedent for exactly this, written when `member` became `system`:
an **engine** migration that re-attributes the rows, prepended to the module
paths so it runs before anything asks. This does the same.

A fresh install has no such rows and the re-attribution does nothing, which is
correct rather than a special case — and both paths have to be tested, because
"works on my machine" here means "works on the machine that already had the
tables".

## What this does not move, and why

- **`forums`** stays. It is the container, and a container is a forum concept.
- **Tags, prefixes, polls** stay. They are attached to topics but they are
  forum furniture; a blog wanting tags is a later argument, and moving them
  speculatively would be the same mistake in the other direction.
- **Moderation** keeps a foot in both: it moderates topics and posts, which are
  now System's, but it also recounts forums. That recount should become
  something Forums does in response to an event rather than something
  moderation reaches over and does — a smaller follow-up, and not worth
  bundling into a change this size.
