Each author account now carries five grantable permissions, editable on
the Users page: publish posts, unpublish posts, delete posts (all three
scoped to the author's own posts), create tags, and approve comments
(scoped to comments on the author's posts, without delete). A bare
author writes and edits their own drafts only. Permission checks gate
the status TRANSITION, so editing an already-published post never
requires the publish permission, and the editor's status dropdown only
offers what the account may do. Tags an author creates are granted to
them automatically, and "creating" an existing off-grant tag is
refused (it would be a self-grant loophole). Existing author accounts
keep publish+unpublish via migration backfill.
Tags the admin attaches outside an author's grants now survive the
author's edits: the form shows them checked-and-locked and the server
re-attaches them on every save.
Every account can change its own password on the new /admin/account
page (current password required); the username in the admin header
links there.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The seeded account is the single admin; it can create author accounts
on the new /admin/users page (username + password) and grant each one
access to specific tags. Authors sign in to a Posts-only panel where
they can write, edit, publish, and unpublish their own posts — every
post must carry at least one granted tag, tags outside the grants are
rejected server-side, and only the admin can create tags or delete
posts (or anything else: pages, comments, settings, and backups stay
admin-only). Admin-only URLs bounce authors to their post list, and
foreign post editors 404.
posts.author_id records ownership; deleting an account keeps its posts
as unowned, admin-managed rows and signs the account out everywhere.
Backups (export v3) store the owner's username per post and re-attach
ownership on import when the account still exists.
Also fixes a latent form bug: a missing newTags field (author forms
don't render it) failed zod validation with an invisible error.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>