Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/syhily/yufan.me/llms.txt

Use this file to discover all available pages before exploring further.

yufan.me supports multiple user accounts with role-based access control. Every admin and authentication event is recorded in an append-only audit log with automatic PII masking and S3 archival, giving you a complete record of who did what and when.

User roles

RolePermissions
adminFull access to all admin features, settings, and user management
authorCan create and edit posts and pages, use the image and music library; cannot change settings or manage users
The first user account is created during the install flow at /admin/setup. Additional accounts are managed from Admin → Users.

Managing users at /admin/users

From the users list you can:
  • Create a new admin or author account by clicking New User and providing a name, email, password, and role.
  • Edit an existing user’s profile — name, email, role, and badge display settings.
  • Reset a password for any user.
  • Soft-delete (deactivate) a user. Deactivated users cannot log in, but their content is preserved and the account row is retained in the database.

Sessions

Sessions are signed HTTP-only cookies backed by Redis. The cookie name is __session and the signing secret is read from the SESSION_SECRET environment variable. Navigate to Admin → Me → Sessions to manage your own active sessions:
  • View all sessions currently active for your account, including the IP address and user agent of each session.
  • Revoke an individual session to force sign-out from a specific device.
  • Revoke all sessions to sign out from every device simultaneously.
The session max age defaults to 30 days and is configurable in Admin → Settings → Advanced → Limits.

Audit log

Every state-mutating operation and auth lifecycle event — login, logout, password reset, post publish, comment deletion, settings update, and more — is recorded in the audit_log table. Read-only actions (list, get, preview) are not logged. Navigate to Admin → Analytics → Audit Log (or Admin → Security → Audit) to browse and filter the log.

Audit entry fields

FieldDescription
actionKebab-case action name, e.g. post_published, user_soft_deleted
actor_idID of the user who performed the action
actor_roleRole of the actor at the time of the action
resource_typeEntity type affected, e.g. post, comment, setting
resource_idID of the specific resource affected
ip_addressClient IP of the request
user_agentBrowser or client UA string
detailsOptional structured metadata about the event
created_atTimestamp the event was recorded

PII masking

Sensitive fields — email, ip, userAgent, phone, cookie, deviceId, authorEmail, authorIp — are automatically wrapped in {E}…{/E} markers before storage. When the audit log is read through the API (for display in the admin UI or CSV export), all tagged values are replaced with ***. The raw values remain in the database storage only and are included in S3 archives.

Filtering

Use the toolbar to narrow the log by:
  • Action — select from the action registry (e.g. post_published, comment_deleted)
  • Resource type — filter to a specific entity type
  • Actor — filter by the user who performed the action
  • Date range — the API clamps dateFrom to the retention boundary, so requests cannot return rows that have already been archived

Retention and archival

Audit rows are retained in the database for auditLogDbRetentionDays (default 30 days, max 90). A daily job at 04:00 server time archives older rows to S3 as compressed JSONL files at the path audit-log/archive/YYYY-MM-DD.jsonl.gz, then deletes the archived rows from the database. S3 archives are kept for auditLogArchiveRetentionDays (default 180 days) before being deleted. The archival pipeline uses Postgres COPY FROM STDIN batching for throughput, with a per-row INSERT fallback if the COPY fails.

Performance

Audit events are buffered in memory and flushed every 50 events or 500 ms, whichever comes first. The batcher listens for SIGTERM, SIGINT, and beforeExit to flush any remaining events before the process shuts down, so events are not lost on graceful shutdown.
Audit log rows are not included in standard pg_dump database backups — the audit_log table is intentionally excluded. Audit data is preserved through the separate S3 archival pipeline. If you need audit records beyond auditLogDbRetentionDays, ensure S3 archival is configured before the first rows age out.
Retention settings are in Admin → Settings → Advanced → Limits: auditLogDbRetentionDays (1–90, default 30) and auditLogArchiveRetentionDays (default 180). Changes take effect on the next daily archival run.

Build docs developers (and LLMs) love