# Content and Global Settings System

## Runtime contract

Phase 15 exposes authenticated Mini App content and permission-scoped Admin configuration APIs. Public responses never trust client lifecycle fields. The database status, UTC visibility window, feature gate, targeting policy, media verification state, and deployment URL allowlist determine what can be returned.

| Area          | Public behavior                                              | Admin lifecycle                               |
| ------------- | ------------------------------------------------------------ | --------------------------------------------- |
| Banners       | Active, in-window, verified public media only                | draft → active ↔ paused → archived            |
| Announcements | Active/scheduled-in-window and language/country eligible     | draft → scheduled/active → expired → archived |
| Tutorials     | Published summaries and slug details                         | draft → published → archived                  |
| Themes        | Bootstrap returns the one validated active theme             | draft → active or archived                    |
| Maintenance   | Middleware uses current UTC window or safe fallback settings | scheduled → active → completed/cancelled      |

Archived content is terminal and no delete API exists. Database triggers reject banner, announcement, and tutorial deletion. `announcement_reads` and `setting_versions` are append-only evidence.

## Content safety

Admin payloads accept plain text, not trusted HTML. The server removes control characters, escapes HTML metacharacters, and creates a minimal paragraph/line-break representation. A future rich editor must still submit an approved structured format to a server sanitizer; it must not make raw `body_html` client-controlled.

Banner actions, tutorial video URLs, managed links, and public URL settings are validated through the deployment URL policy. Credentials, unapproved schemes, and hosts outside the allowlist are rejected.

## Media boundary

Content may reference only `media_files` rows whose status is `verified` and scope is `public`. `GET /media/:mediaId` resolves a stable public ID, validates filesystem containment, verifies the physical byte length against metadata, and returns immutable caching plus a SHA-256-derived ETag. Quarantined, private, rejected, deleted, missing, size-mismatched, and path-escaping files fail as not found.

Phase 15 deliberately does not accept JSON/base64 or arbitrary-path uploads. The Admin frontend/media uploader phase must quarantine input, inspect MIME signatures and image limits, then promote only verified files.

## Global configuration

- Settings use a closed key policy, stored type validation, optimistic version, change reason, and immutable next-version history.
- Feature flags are limited to known client features plus registration/broadcast controls. Phase 15 supports boolean enablement and deterministic percentage rollout; arbitrary executable/targeting rules are rejected.
- Theme tokens use closed light/dark palettes, bounded radius, controlled blur, and reduced-motion values. A generated unique slot permits only one active theme.
- New currencies begin inactive and non-settlement. Once the ledger exists, settlement precision, rounding mode, and activation cannot be changed through the API.
- Maintenance windows use UTC timestamps, ordered ranges, optimistic versions, and explicit transitions.

## Admin security

Reads, content edits, publishing, settings changes, link changes, flag changes, themes, currencies, and maintenance use distinct permissions. All Admin routes require the configured Admin IP policy and authenticated server session. Mutations additionally require session-bound CSRF, sensitive-route rate limiting, strict Zod payloads, optimistic versions, and audit context.

## Deployment checklist

1. Run `npm run verify:environment`, `npm run migrate:dry-run`, and `npm run check`.
2. Inspect the `020` preflight requirements in `DATABASE-OPERATIONS.md`.
3. Apply migrations and seeds in staging before production.
4. Keep approved public files under the configured public media directory; never point metadata at private or quarantine paths.
5. Review the managed URL deployment allowlist before enabling editable URLs.
6. Assign publishing and global-setting permissions narrowly.
7. Verify light/dark themes, UTC content windows, targeting, CSRF, media 404 behavior, and maintenance exemptions.

No live MySQL instance, Telegram environment, external URL, or deployment filesystem was modified while Phase 15 was built.
