feat(teams): the forum schema, the operator's two switches, and the ack gate

The whole forum schema lands at once — threads, posts, the moderation ledger and
upload attribution — including the columns only phase 5's discussion threads use.
That is TEAMS.md 5.1's split BY LAYER rather than by feature: phase 5 opens paths
instead of migrating data.

Three settings keys, and only one of them is ordinary. `teams_forums_enabled` and
`teams_forum_images` are enum keys on the existing admin settings endpoint;
`teams_forum_images` also carries a server-side PRECONDITION, which is why the
three live in their own model rather than in the generic setMany() loop where a
reader would never find it.

The gate is the server's. `PUT teams_forum_images = 'uploads'` is rejected 400
unless the same request carries the acknowledgement version — the admin checkbox
is how the gate is presented, never the gate. What is stored is the TEXT VERSION,
so "which wording did they agree to" is answerable later; settings already record
updated_by/updated_at, and an activity_log row puts it in the staff audit trail.

A reworded notice makes a stored acknowledgement stale, and neither obvious answer
is right: uploads KEEP WORKING, and no other forum setting may be saved until it is
re-given. Non-destructive, and impossible to ignore.

Both reads fail closed. A DB fault reports the forum off and images disabled — a
forum that 404s for a minute is the cheap failure; a policy that is not a policy
is not.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-18 07:23:15 -05:00
parent 7ed2ac9983
commit 11fd9821bf
5 changed files with 325 additions and 1 deletions

View File

@@ -16,6 +16,18 @@ const PUBLIC_KEYS = [
'theme_visual', // preset/custom colors, fonts, radii (JSON). See THEMING_AND_NAV.md §6.1.
'brand_assets', // uploaded logo/hero/favicon overrides (JSON). §6.3.
'nav_public', // public site nav overrides (JSON). §6.4.
// The two Team-forum controls (TEAMS.md §5.5.6). The client needs the first to
// know whether to render the forum panel at all, and the second to decide which
// composer to show — an upload control that 404s is worse than no control.
// Neither is sensitive.
//
// `teams_forum_uploads_ack` is deliberately NOT here: who accepted a liability
// notice is operator detail, exactly as `failure_reason` is in MODULE_API.md
// §2.9. And publishing the mode does not move the DECISION client-side — the
// server still resolves what renders (§5.5.3); the client is only told which
// composer to draw.
'teams_forums_enabled',
'teams_forum_images',
]
// Admin-configurable theming & navigation (docs/website/THEMING_AND_NAV.md).