summaryrefslogtreecommitdiff
path: root/www/caps
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
committercashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
commit4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch)
treec296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /www/caps
downloadrelic-master.tar.gz
initial commitHEADmaster
Diffstat (limited to 'www/caps')
-rw-r--r--www/caps/admin-v-setup.md461
-rw-r--r--www/caps/impl.md111
-rw-r--r--www/caps/index.md405
-rw-r--r--www/caps/login-groups.md128
-rw-r--r--www/caps/ref.html454
5 files changed, 1559 insertions, 0 deletions
diff --git a/www/caps/admin-v-setup.md b/www/caps/admin-v-setup.md
new file mode 100644
index 0000000..db1b412
--- /dev/null
+++ b/www/caps/admin-v-setup.md
@@ -0,0 +1,461 @@
+# Differences Between Setup and Admin Users
+
+This document explains the distinction between [Setup users][caps] and
+[Admin users][capa]. For other information about use types, see:
+
+* [Administering User Capabilities](./)
+* [How Moderation Works](../forum.wiki#moderation)
+* [Users vs Subscribers](../alerts.md#uvs)
+* [Defense Against Spiders](../antibot.wiki)
+
+
+## <a id="philosophy"></a>Philosophical Core
+
+The Setup user "owns" the Fossil repository and may delegate a subset of
+that power to one or more Admin users.
+
+The Setup user can grant Admin capability and take it away, but Admin
+users cannot grant themselves Setup capability, either directly via the
+Admin → Users UI page or via any indirect means. (If you discover
+indirect means to elevate Admin privilege to Setup, it's a bug, so
+please [report it][forum]!)
+
+It is common for the Setup user to have administrative control over the
+host system running the Fossil repository, whereas it makes no sense for
+Admin users to have that ability. If an Admin-only user had `root`
+access on a Linux box running the Fossil instance they are an Admin on,
+they could elevate their capability to Setup in several ways. (The
+`fossil user` command, the `fossil sql` command, editing the repository
+DB file directly, etc.) Therefore, if you wish to grant someone
+Setup-like capability on a Fossil repository but you're unwilling to
+give them a login on the host system, you probably want to grant
+them Admin capability instead.
+
+Admin power is delegated from Setup. When a Setup user grants Admin
+capability, it is an expression of trust in that user's judgement.
+
+Admin-only users must not fight against the policies of the Setup user.
+Such a rift would be just cause for the Setup user to strip the Admin
+user's capabilities. This may then create a fork in the project’s
+development effort as the ex-Admin takes their clone and stands it up
+elsewhere, so they may become that fork’s Setup user.
+
+A useful rule of thumb here is that Admin users should only change
+things that the Setup user has not changed from the stock configuration.
+In this way, an Admin-only user can avoid overriding the Setup user's
+choices.
+
+You can also look at the role of Admin from the other direction, up
+through the [user power hierarchy][ucap] rather than down from Setup. An
+Admin user is usually a “super-developer” role, given full control over
+the repository’s managed content: versioned artifacts in [the hash tree][bc],
+[unversioned content][uv], forum posts, wiki articles,
+tickets, etc.
+
+We’ll explore these distinctions in the rest of this document.
+
+[bc]: ../blockchain.md
+[ucap]: ./index.md#ucap
+[uv]: ../unvers.wiki
+
+
+## <a id="binary"></a>No Granularity
+
+Fossil doesn’t make any distinction between these two user types beyond
+this binary choice: Setup or Admin.
+
+A few features of Fossil are broken down so that only part of the
+feature is accessible to Admin, with the rest left only to Setup users,
+but for the most part each feature affected by this distinction is
+either Admin + Setup or Setup-only.
+
+We could add more capability letters to break down individual
+sub-features, but we’d run out of ASCII alphanumerics pretty quickly,
+and we might even run out of ASCII punctuation and symbols. Then would
+we need to shift to Unicode?
+
+Consider the Admin → Settings page, which is currently restricted to
+Setup users only: you might imagine breaking this up into several
+subsets so that some settings can be changed by Admin users. Is that a
+good idea? Maybe, but it should be done only after due consideration. It
+would definitely be wrong to assign a user capability bit to *each*
+setting on that page.
+
+Now consider the opposite sort of case, Admin → Skins. Fossil grants
+Admin users full access to this page so that the Admins can maintain and
+extend the skin as the repository evolves, not so Admins can switch the
+entire skin to another without consulting with the Setup user first. How
+would Fossil decide, using user capabilities only, which skin changes
+the Admin user is allowed to do, and which must be left to Setup? Do we
+assign a separate capability letter to each step in `/setup_skin`? Do we
+assign one more each to the five sections of a skin? (Header, Footer,
+CSS, JavaScript, and Details.) It quickly becomes unmanageable.
+
+
+
+## <a id="capgroups"></a>Capability Groups
+
+We can break up the set of powers the Admin user capability grants into
+several groups, then defend each group as a coherent whole.
+
+
+### <a id="security"></a>Security
+
+While establishing the Fossil repository's security policy is a task for
+the Setup user, *maintaining* that policy is something that Fossil
+allows a Setup user to delegate to trustworthy users via the Admin user
+capability:
+
+* **Manage users**: The only thing an Admin-only user cannot do on the
+ Admin → Users page is grant Setup capability, either to themselves
+ or to other users. The intent is that Admin users be able to take
+ some of the load of routine user management tasks off the shoulders
+ of the Setup user: delete accounts created by spammers, fix email
+ alert subscriptions, reset passwords, etc.
+
+* **Security audit**: The Admin → Security-Audit page runs several
+ tests on the Fossil repository's configuration, then reports
+ potential problems it found and offers canned solutions. Those
+ canned solutions do not do anything that an Admin-user could not do
+ via other means, so this page offers the Admin-only user no more
+ power than they otherwise had. For example, this page's "Take it
+ Private" feature can also be done manually via Admin → Users. This
+ page is a convenience, not a grant of new power to the Admin-only
+ user.
+
+* **Logging**:<a id="log"></a> Admin-only users get to see the various
+ Fossil logs in case they need to use them to understand a problem
+ they're empowered to solve. An obvious example is a spam attack: the
+ Admin might want to find the user's last-used IP, see if they cloned
+ the repository, see if they attempted to brute-force an existing
+ login before self-registering, etc.
+
+Some security-conscious people might be bothered by the fact that
+Admin-only users have these abilities. Think of a large IT organization:
+if the CIO hires a [tiger team][tt] to test the company's internal IT
+defenses, the line grunts fix the reported problems, not the CIO.
+
+
+### <a id="administrivia"></a>Administrivia
+
+It is perfectly fine for a Fossil repository to only have Setup users,
+no Admin users. The smaller the repository, the more likely the
+repository has no Admin-only users. If the Setup user neither needs nor
+wants to grant Admin power to others, there is no requirement in Fossil
+to do so. [Setup capability is a pure superset of Admin capability.][sia]
+
+As the number of users on a Fossil repository grows, the value in
+delegating administrivia also grows, because the Setup user typically
+has other time sinks they consider more important.
+
+Admin users can take over the following routine tasks on behalf of the
+Setup user:
+
+* **Shunning**: After user management, this is one of the greatest
+ powers of an Admin-only user. Fossil grants access to the Admin →
+ Shunned page to Admin users rather than reserve it to Setup users
+ because one of the primary purposes of [the Fossil shunning
+ system][shun] is to clean up after a spammer, and that's
+ exactly the sort of administrivia we wish to delegate to Admin users.
+
+ Coupled with the Rebuild button on the same page, an Admin user has
+ the power to delete the repository's entire
+ [hash tree][bc]! This makes this feature a pretty good
+ razor in deciding whether to grant someone Admin capability: do you
+ trust that user to shun Fossil artifacts responsibly?
+
+ Realize that shunning is cooperative in Fossil. As long as there are
+ surviving repository clones, an Admin-only user who deletes the
+ whole hash tree has merely caused a nuisance. An Admin-only user
+ cannot permanently destroy the repository unless the Setup user has
+ been so silly as to have no up-to-date clones.
+
+* **Moderation**: According to [the user power hierarchy][ucap],
+ Admins are greater than Moderators, so control over
+ what Moderators can do clearly belongs to both Admins and to the
+ Setup user(s).
+
+* **Status**: Although the Fossil `/stat` page is visible to every
+ user with Read capability, there are several additional things this
+ page gives access to when a user also has the Admin capability:
+
+ * <p>[Email alerts][ale] and [backoffice](../backoffice.md)
+ status. Admin-only users cannot modify the email alerts setup,
+ but they can see some details about its configuration and
+ current status.</p>
+
+ * <p>The `/urllist` page, which is a read-only page showing the
+ ways the repository can be accessed and how it has been accessed
+ in the past. Logically, this is an extension to logging,
+ [covered above](#log).</p>
+
+ * <p>The Fossil repository SQL schema. This is not particularly
+ sensitive information, since you get more or less the same
+ information when you clone the repository. It's restricted to
+ Admin because it's primarily useful in debugging SQL errors,
+ which happen most often when Fossil itself is in flux and the
+ schema isn't being automatically updated correctly. That puts
+ this squarely into the "administrivia" category.</p>
+
+ * <p>Web cache status, environment, and logging: more
+ administrivia meant to help the Admin debug problems.</p>
+
+* **Configure search**
+
+[ale]: ../alerts.md
+[shun]: ../shunning.wiki
+
+
+### <a id="cosmetics"></a>Cosmetics
+
+While the Setup user is responsible for setting up the initial "look" of
+a Fossil repository, the Setup user entrusts Admin users with
+*maintaining* that look. An Admin-only user therefore has the following
+special abilities:
+
+* Modify the repository skin
+
+* Create and modify URL aliases
+
+* Manage the "ad units" feature, if enabled.
+
+* Adjust the `/timeline` display preferences.
+
+* Change the "logo" element displayed by some skins.
+
+These capabilities allow an Admin-only user to affect the branding and
+possibly even the back-end finances of a project. This is why we began
+this document with a philosophical discussion: if you cannot entrust a
+user with these powers, you should not grant that user Admin capability.
+
+
+## <a id="clones"></a>Clones and Backups
+
+Fossil is a *distributed* version control system, which has direct
+effects on the “Setup user” concept in the face of clones. When you
+clone a repository, your local user becomes a Setup user on the local
+clone even if you are not one on the remote repository. This may be
+surprising to you, but it should also be sensible once you realize that
+your operating system will generally give you full control over the
+local repository file. What use trying to apply remote restrictions on
+the local file, then?
+
+The distinctions above therefore are intransitive: they apply only
+within a single repository instance.
+
+Fossil behaves differently when you do a clone as a user with Setup
+capability on the remote repository, which primarily has effects on the
+fidelity of clone-as-backup, which we cover [elsewhere](../backup.md).
+We strongly encourage you to read that document if you expect to use a
+clone as a complete replacement for the remote repository.
+
+
+## <a id="apsu"></a>The All-Powerful Setup User
+
+Setup users get [every user capability](./ref.html) of Fossil except for
+[two exceptionally dangerous capabilities](#dcap), which they can later
+grant to themselves or to others.
+
+In addition, Setup users can use every feature of the Fossil UI. If Fossil can do a
+thing, a Setup user on that repo can make Fossil do it.
+
+Setup users can do many things that Admin users cannot. They may not
+only use all of the Admin UI features, they may also:
+
+* See record IDs (RIDs) on screens that show them
+* See the MIME type of attachments on [`/ainfo` pages](/help/www/ainfo)
+* See a remote repo’s HTTP [cache status](/help/www/cachestat)
+ and [pull cache entries](/help/www/cacheget)
+* Edit a Setup user’s account!
+
+The “Admin” feature of Fossil UI is so-named because Admin users can use
+about half of its functions, but only Setup can use these pages:
+
+* **Access**: This page falls under the [Security](#security)
+ category above, but like Configuration, it's generally something set
+ up once and never touched, so only Setup users should change it.
+
+* **Configuration**: This page nominally falls
+ under [Cosmetics](#cosmetics) above, but it's such a core part of the Fossil
+ configuration — something every Setup user is expected to fully
+ specify on initial repository setup — that we have trouble
+ justifying any case where an Admin-only user would have good cause
+ to modify any of it. This page is generally set up once and then
+ never touched again.
+
+* **Email-Server**: This is an experimental SMTP server feature which
+ is currently unused in Fossil. Should we get it working, it will
+ likely remain Setup-only, since it will likely be used as a
+ replacement for the platform’s default SMTP server, a powerful
+ position for a piece of software to take.
+
+* **Login-Group**: [Login groups][lg] allow one Fossil repository to
+ delegate user access to another. Since an Admin-only user on one
+ repo might not have such access to another repo on the same host
+ system, this must be a Setup-only task.
+
+* **Notification**: This is the main UI for setting up integration
+ with a platform’s SMTP service, for use in sending out [email
+ notifications][ale]. Because this screen can set commands to execute
+ on the host, and because finishing the configuration requires a
+ login on the Fossil host system, it is not appropriate to give Admin
+ users access to it.
+
+* **Settings**: The [repository settings][rs] available via Admin →
+ Settings have too wide a range of power to allow modification by
+ Admin-only users:
+
+ * <p><b>Harmless</b>: Admin-only users on a repository may well
+ have checkin rights on the repository, so the fact that
+ versionable settings like `crlf-glob` can also be set at the
+ repository level seems like a thing we might want to allow
+ Admin-only users the ability to change. Since Fossil currently
+ has no way to allow only some settings to be changed by
+ Admin-only users and some not, we can't just show these harmless
+ settings to Admin-only users.</p>
+
+ * <p><b>Low-Risk</b>: The <tt>admin-log</tt> setting controls
+ whether the Fossil admin log is generated. Since we've <a
+ href="#log">already decided</a> that Admin-only users can see
+ this log, it seems fine that the Admin users can choose whether
+ this log gets generated in the first place.</p>
+
+ <p>There's a small risk that a rogue Admin user could disable
+ the log before doing something evil that the log would capture,
+ so ideally, we'd want to restrict changing this setting from 1
+ to 0 to Setup only while allowing Admin-only users to change it
+ from 0 to 1. Fossil doesn't currently allow that.</p>
+
+ * <p><b>Risky</b>: The <tt>https-login</tt> setting falls under
+ the "Security" section above, but it should probably never be
+ adjusted by Admin-only users. Sites that want it on will never
+ want it to be disabled without a very good reason.</p>
+
+ <p>There is also an inverse risk: if the site has a front-end
+ HTTPS proxy that uses HTTP to communicate over localhost to
+ Fossil, enabling this setting will create an infinite redirect
+ loop! (Ask me how I know.)</p>
+
+ * <p><b>Dangerous</b>: The <tt>email-send-command</tt> setting
+ could allow a rogue Admin to run arbitrary commands on the host
+ system, unless it's prevented via some kind of host-specific
+ restriction. (chroot, jails, SELinux, VMs, etc.) Since it makes
+ no sense to trust Admin-only users with <tt>root</tt> level
+ access on the host system, we almost certainly don't want to
+ allow them to change such settings.</p>
+
+* **SQL**: The Admin → SQL feature allows the Setup user to enter raw
+ SQL queries against the Fossil repository via Fossil UI. This not
+ only allows arbitrary ability to modify the repository hash tree
+ and its backing data tables, it can probably also be used to damage
+ the host such as via `PRAGMA temp_store = FILE`.
+
+* **Tickets**: This section allows input of arbitrary TH1 code that
+ runs on the server, affecting the way the Fossil ticketing system
+ works. The justification in the **TH1** section below therefore
+ applies.
+
+* **TH1**: The [TH1 language][th1] is quite restricted relative to the
+ Tcl language it descends from, so this author does not believe there
+ is a way to damage the Fossil repository or its host via the Admin →
+ TH1 feature, which allows execution of arbitrary TH1 code within the
+ repository's execution context. Nevertheless, interpreters are a
+ well-known source of security problems, so it seems best to restrict
+ this feature to Setup-only users as long as we lack a good reason
+ for Admin-only users to have access to it.
+
+* **Transfers**: This is for setting up TH1 hooks on various actions,
+ so the justification in the **TH1** section above applies.
+
+* **Wiki**: These are mainly cosmetic and usability settings. We might
+ open this up to Admin users in the future.
+
+Just remember, [user caps affect Fossil’s web interfaces only][webo]. A
+user is a Setup user by default on their local clone of a repo, and
+Fossil’s ability to protect itself against malicious (or even simply
+incorrect) pushes is limited. Someone with clone and push capability on
+your repo could clone it, modify their local repo, and then push the
+changes back to your repo. Be careful who you give that combination of
+capabilities to!
+
+When you run [`fossil ui`][fui], you are the Setup user on that repo
+through that UI instance, regardless of the capability set defined in
+the repo’s user table. This is true even if you cloned a remote repo
+where you do not have Setup caps. This is why `ui` always binds to
+`localhost` without needing the `--localhost` flag: in this mode, anyone
+who can connect to that repo’s web UI has full power over that repo.
+
+
+## <a id="dcap"></a>Dangerous Capabilities Initially Denied to Everyone
+
+There are two capabilities that Fossil doesn’t grant by default to Setup
+or Admin users automatically. They are exceptionally dangerous, so
+Fossil makes these users grant themselves (or others) these capabilities
+deliberately, hopefully after careful consideration.
+
+
+### <a id="y"></a>Write Unversioned
+
+Fossil currently doesn’t distinguish the sub-operations of
+[`fossil uv`](/help/uv); they’re all covered by [**WrUnver**][capy]
+(“y”) capability. Since some of these operations are unconditionally
+destructive due to the nature of unversioned content, and since this
+goes against Fossil’s philosophy of immutable history, nobody gets cap
+“y” on a Fossil repo by default, not even the Setup or Admin users. A
+Setup or Admin user must grant cap “y” to someone — not necessarily
+themselves! — before modifications to remote
+unversioned content are possible.
+
+Operations on unversioned content made without this capability affect
+your local clone only. In this way, your local unversioned file table
+can have different content from that in its parent repo. This state of
+affairs will continue until your user either gets cap “y” and syncs that
+content with its parent or you say `fossil uv revert` to make your local
+unversioned content table match that of its parent repo.
+
+
+### <a id="x"></a>Private Branch Push
+
+For private branches to remain private, they must never be accidentally
+pushed to a public repository. It can be [difficult to impossible][shun]
+to recover from such a mistake, so nobody gets [**Private**][capx] (“x”)
+capability on a Fossil repo by default, not even Admin or Setup users.
+
+There are two common uses for private branches.
+
+One use is part of a local social contract allowing individual
+developers to work on some things in private until they’re ready to push
+them up to the parent repository. This goes against [a core tenet][fdp]
+of Fossil’s design philosophy, but Fossil allows it, so some development
+organizations do this. If yours is one of these, you might give cap “x”
+to the “developer” category.
+
+The other use is in development organizations that follow the Fossil
+philosophy, where you do not work in private unless you absolutely must.
+You may have a public-facing project — let’s call it “SQLite” for the
+sake of argument — but then someone comes along and commissions a custom
+modification to your project which they wish to keep proprietary. You
+do your work on a private branch, which you absolutely must never push
+to the public repo, because that would be illegal. (Breach of contract,
+copyright violation on a work-for-hire agreement, etc.) If you are using
+Fossil in this way, we recommend that you give “x” capability to a
+special developer account only, if at all, to minimize the chance of an
+accidental push.
+
+
+[capa]: ./ref.html#a
+[caps]: ./ref.html#s
+[capx]: ./ref.html#x
+[capy]: ./ref.html#y
+
+[fcp]: https://fossil-scm.org/home/help/configuration
+[fdp]: ../fossil-v-git.wiki#devorg
+[forum]: https://fossil-scm.org/forum/
+[fui]: /help/ui
+[lg]: ./login-groups.md
+[rs]: https://fossil-scm.org/home/doc/trunk/www/settings.wiki
+[sia]: https://fossil-scm.org/home/artifact?ln=1259-1260&name=0fda31b6683c206a
+[snoy]: https://fossil-scm.org/forum/forumpost/00e1c4ecff
+[th1]: ../th1.md
+[tt]: https://en.wikipedia.org/wiki/Tiger_team#Security
+[webo]: ./#webonly
diff --git a/www/caps/impl.md b/www/caps/impl.md
new file mode 100644
index 0000000..1f9b5a4
--- /dev/null
+++ b/www/caps/impl.md
@@ -0,0 +1,111 @@
+# Implementation Details of User Capabilities
+
+## <a id="choices"></a>Capability Letter Choices
+
+We [assigned][ref] user capability characters using only lowercase ASCII
+letters at first, so those are the most important within Fossil: they
+control the functions most core to Fossil’s operation. Once we used up
+most of the lowercase letters, we started using uppercase, and then
+during the development of the [forum feature][for] we assigned most of
+the decimal numerals. All of the lowercase ASCII letters are now
+assigned. Eventually, we might have to start using ASCII
+punctuation and symbols. We expect to run out of reasons to define new caps before
+we’re forced to switch to Unicode, though the possibilities for [mnemonic][mn]
+assignments with emoji are intriguing. <span style="vertical-align:
+bottom">😉</span>
+
+The existing caps are usually mnemonic, especially among the
+earliest and therefore most central assignments, made when we still had
+lots of letters to choose from. There is still hope for good future
+mnemonic assignments among the uppercase letters, which are mostly still
+unused.
+
+
+## <a id="bitfield"></a>Why Not Bitfields?
+
+Some may question the use of ASCII character strings for [capability
+sets][ucap] instead of bitfields, which are more efficient, both in
+terms of storage and processing time.
+
+Fossil handles these character strings in one of two ways. For most HTTP
+hits, Fossil [expands][sexp] the string into a [`struct` full of
+flags][sff] so that later code can just do simple Boolean tests. In a
+minority of cases, where Fossil only needs to check for the presence of
+a single flag, it just does a [`strchr()` call][sc] on the string
+instead.
+
+Both methods are slower than bit testing in a bitfield, but keep the
+execution context in mind: at the front end of an HTTP request handler,
+where the nanosecond differences in such implementation details are
+completely swamped by the millisecond scale ping time of that repo’s
+network connection, followed by the required I/O to satisfy the request.
+Either method is plenty fast in that context.
+
+In exchange for this immeasurable cost per hit, we get human-readable
+capability sets.
+
+
+## <a id="filter"></a>Why Doesn’t Fossil Filter “Bad” Artifacts on Sync?
+
+Fossil is more trusting about the content it receives from a remote
+clone during sync than you might expect. Common manifestations of this
+design choice are:
+
+1. A user may be able to impersonate other users. This can be
+ [accidental](./index.md#defuser) as well as purposeful.
+
+2. If your local system clock is out-of-sync with absolute time,
+ artifacts committed to that repo will appear with the “wrong” time
+ when sync’d. If the time sync error is big enough, it can make
+ check-ins appear to go back in time and other bad effects.
+
+3. You can purposely overwrite good timestamps with bad ones and push
+ those changes up to the remote with no interference, even though
+ Fossil tries to make that a Setup-only operation.
+
+All of this falls out of two of Fossil’s design choices: sync is
+all-or-nothing, and [the Fossil hash tree][bc] is immutable. Fossil
+would have to violate one or both of these principles to filter such
+problems out of incoming syncs.
+
+We have considered auto-[shunning][shun] “bad” content on sync, but this
+is [difficult][asd] due to [the design of the sync protocol][dsp]. This
+is not an impossible set of circumstances, but implementing a robust
+filter on this input path would be roughly as difficult as writing a
+basic [inter-frame video codec][ifvc]: do-able, but still a lot of
+work. Patches to do this will be thoughtfully considered.
+
+We can’t simply change content as it arrives. Such manipulations would
+change the artifact manifests, which would change the hashes, which
+would require rewriting all parts of the block chain from that point out
+to the tips of those branches. The local Fossil repo must then go
+through the same process as the remote one on subsequent syncs in order
+to build up a sync sequence that the remote can understand. Even if
+you’re willing to accept all of that, this would break all references to
+the old artifact IDs in forum posts, wiki articles, check-in comments,
+tickets, etc.
+
+The bottom line here is that [**Clone**](./ref.html#g) and
+[**Write**](./ref.html#i) are a potent combination of user capabilities.
+Be careful who you give that pair to!
+
+
+-----
+
+*[Back to Administering User Capabilities](./)*
+
+<!-- add padding so anchor links always scroll ref’d section to top -->
+<div style="height: 75em"></div>
+
+[asd]: https://fossil-scm.org/forum/forumpost/ce4a3b5f3e
+[bc]: ../blockchain.md
+[dsp]: https://fossil-scm.org/fossil/doc/trunk/www/sync.wiki
+[for]: ./forum.wiki
+[ifvc]: https://en.wikipedia.org/wiki/Inter_frame
+[mn]: https://en.wikipedia.org/wiki/Mnemonic
+[ref]: ./ref.html
+[sexp]: /artifact?ln=1223-1298&name=889d6724
+[sff]: /artifact?ln=80-117&name=52d2860f
+[sc]: https://en.cppreference.com/w/c/string/byte/strchr
+[shun]: ../shunning.wiki
+[ucap]: ./index.md#ucap
diff --git a/www/caps/index.md b/www/caps/index.md
new file mode 100644
index 0000000..3492e5e
--- /dev/null
+++ b/www/caps/index.md
@@ -0,0 +1,405 @@
+# Administering User Capabilities (a.k.a. Permissions)
+
+Fossil includes a powerful [role-based access control system][rbac]
+which affects which users have which capabilities(^Some parts of the
+Fossil code call these “permissions” instead, but since there is [a
+clear and present risk of confusion](#webonly) with operating system
+level file permissions in this context, we avoid using that term for
+Fossil’s RBAC capability flags in these pages.) within a given
+[served][svr] Fossil repository. We call this the “caps” system for
+short.
+
+Fossil stores a user’s caps as an unordered string of ASCII characters,
+one capability per, [currently](./impl.md#choices) limited to
+[alphanumerics][an]. Caps are case-sensitive: “**A**” and “**a**” are
+different user capabilities.
+
+This is a complex topic, so some sub-topics have their own documents:
+
+1. [Login Groups][lg]
+2. [Implementation Details](./impl.md)
+3. [User Capability Reference](./ref.html)
+
+[an]: https://en.wikipedia.org/wiki/Alphanumeric
+[avs]: ./admin-v-setup.md
+[lg]: ./login-groups.md
+[rbac]: https://en.wikipedia.org/wiki/Role-based_access_control
+
+
+## <a id="ucat"></a>User Categories
+
+Before we explain individual user capabilities and their proper
+administration, we want to talk about an oft-overlooked and
+misunderstood feature of Fossil: user categories.
+
+Fossil defines four user categories. Two of these apply based on the
+user’s login status: **nobody** and **anonymous**. The other two act
+like Unix or LDAP user groups: **reader** and **developer**. Because we
+use the word “group” for [another purpose][lg] in Fossil, we will
+avoid using it that way again in this document. The correct term in
+Fossil is “category.”
+
+Fossil user categories give you a way to define capability sets for four
+hard-coded situations within the Fossil C source code. Logically
+speaking:
+
+> *(developer* &or; *reader)* &ge; *anonymous* &ge; *nobody*
+
+When a user visits a [served Fossil repository][svr] via its web UI,
+they initially get the capabilities of the “nobody” user category. This
+category would be better named “everybody” because it applies whether
+you’re logged in or not.
+
+When a user logs in as “anonymous” via [`/login`](/help?name=/login) they
+get all of the “nobody” category’s caps plus those assigned to the
+“anonymous” user category. It would be better named “user” because it
+affects all logged-in users, not just those logged in via Fossil’s
+anonymous user feature.
+
+When a user with either the “reader” ([**u**][u]) or “developer”
+([**v**][v]) capability letter logs in, they get their [individual user
+caps](#ucap) plus those assigned to this special user category. They
+also get those assigned to the “anonymous” and “nobody” categories.
+
+Because “developer” users do not automatically inherit “reader” caps,
+it is standard practice to give both letters to your “developer” users:
+**uv**. You could instead just assign cap **u** to the “developer”
+category.
+
+Fossil shows how these capabilities apply hierarchically in the user
+editing screen (Admin → Users → name) with the `[N]` `[A]` `[D]` `[R]`
+tags next to each capability check box. If a user gets a capability from
+one of the user categories already assigned to it, there is no value in
+redundantly assigning that same cap to the user explicitly. For example,
+with the default **ei** cap set for the “developer” category, the cap
+set **ve** is redundant because **v** grants **ei**, which includes
+**e**.
+
+We suggest that you lean heavily on these fixed user categories when
+setting up new users. Ideally, your users will group neatly into one of
+the predefined categories, but if not, you might be able to shoehorn
+them into our fixed scheme. For example, the administrator of a
+wiki-only Fossil repo for non-developers could treat the “developer”
+user category as if it were called “author,” and a forum-only repo could
+treat the same category as if it were called “member.”
+
+There is currently no way to define custom user categories.
+
+[svr]: ../server/
+
+
+## <a id="ucap"></a>Individual User Capabilities
+
+When one or more users need to be different from the basic capabilities
+defined in user categories, you can assign caps to individual users. You
+may want to have the [cap reference][ref] open when doing such work.
+
+It is useful at this time to expand on the logical
+expression [above](#cat), which covered only the four fixed user categories.
+When we bring the individual user capabilities into it, the complete
+expression of the way Fossil implements user power becomes:
+
+> *setup* &ge; *admin* &ge; *moderator* &ge; *(developer* &or; *reader)* &ge; *[subscriber]* &ge; *anonymous* &ge; *nobody*
+
+The two additions at the top are clear: [setup is all-powerful][apsu],
+and since admin users have [all capabilities][ref] except for Setup
+capability, they are [subordinate only to the setup user(s)][avsp].
+
+The moderator insertion could go anywhere from where it’s shown now down
+to above the “anonymous” level, depending on what other caps you give to
+your moderators. Also, there is not just one type of moderator: Fossil
+has [wiki][l], [ticket][q], and [forum][5] moderators, each
+independent of the others. Usually your moderators are fairly
+high-status users, with developer capabilities or higher, but Fossil
+does allow the creation of low-status moderators.
+
+The placement of “subscriber” in that hierarchy is for the
+sort of subscriber who has registered an account on the repository
+purely to [receive email alerts and announcements][7]. Users with
+additional caps can also be subscribers, but not all users *are* in fact
+subscribers, which is why we show it in square brackets. (See [Users vs
+Subscribers](../alerts.md#uvs).)
+
+[apsu]: ./admin-v-setup.md#apsu
+[avsp]: ./admin-v-setup.md#philosophy
+
+
+## <a id="new"></a>New Repository Defaults
+
+Fossil creates one user account in new repos, which is named after your
+OS user name [by default](#defuser).
+
+Fossil gives the initial repository user the [all-powerful Setup
+capability][apsu].
+
+Users who visit a [served repository][svr] without logging in get the
+“nobody” user category’s caps which default to
+**[g][g][j][j][o][o][r][r][z][z]**: clone the repo, read the wiki,
+check-out files via the web UI, view tickets, and pull version archives.
+This default is suited to random passers-by on a typical FOSS project’s
+public web site and its code repository.
+
+Users who [prove they are not a bot][bot] by logging in — even if only
+as “anonymous” — get the “nobody” capability set plus
+**[h][h][m][m][n][n][c][c]**: see internal hyperlinks, append to
+existing wiki articles, file new tickets, and comment on existing
+tickets. We chose these additional capabilities as those we don’t want
+bots to have, but which a typical small FOSS project would be happy to
+give anonymous humans visiting the project site.
+
+The “reader” user category is typically assigned to users who want to be
+identified within the repository but who primarily have a passive role
+in the project. The default capability set on a Fossil repo adds
+**[k][k][p][p][t][t][w][w]** caps to those granted by “nobody” and
+“anonymous”. This category is not well-named, because the default caps
+are all about modifying repository content: edit existing wiki pages,
+change one’s own password, create new ticket report formats, and modify
+existing tickets. This category would be better named “participant”.
+
+Those in the “developer” category get the “nobody” and “anonymous” cap
+sets plus **[e][e][i][i]**: view
+sensitive user material and check in changes.
+
+[bot]: ../antibot.wiki
+
+
+## <a id="pvt"></a>Consequences of Taking a Repository Private
+
+When you click Admin → Security-Audit → “Take it private,” one of the
+things it does is set the user capabilities for the “nobody” and
+“anonymous” user categories to blank, so that users who haven’t logged
+in can’t even see your project’s home page, and the option to log in as
+“anonymous” isn’t even offered. Until you log in with a user name, all
+you see is the repository’s skin and those few UI elements that work
+without any user capability checks at all, such as the “Login” link.
+
+Beware: Fossil does not reassign the capabilities these users had to
+other users or to the “reader” or “developer” user category! All users
+except those with Setup capability will lose all capabilities they
+inherited from “nobody” and “anonymous” categories. Setup is the [lone
+exception][apsu].
+
+If you will have non-Setup users in your private repo, you should parcel
+out some subset of the capability set the “nobody” and “anonymous”
+categories had to other categories or to individual users first.
+
+
+## <a id="read-v-clone"></a>Reading vs. Cloning
+
+Fossil has two capabilities that are often confused:
+[**Read**](./ref.html#o) and [**Clone**](./ref.html#g).
+
+The **Read** capability has nothing to do with reading data from a local
+repository, because [caps affect Fossil’s web interfaces
+only](#webonly). Once you’ve cloned a remote repository to your local
+machine, you can do any reading you want on that repository irrespective
+of whether your local user within that repo has <b>Read</b> capability.
+The repo clone is completely under your user’s power at that point,
+affected only by OS file permissions and such. If you need to prevent
+that, you want to deny **Clone** capability instead.
+
+Withholding the **Read** capability has a different effect: it
+prevents a web client from viewing [embedded documentation][edoc],
+using [the file browser](/help?name=/dir),
+exploring the [history](/help?name=/timeline) of check-ins,
+and pulling file content via the [`/artifact`](/help?name=/artifact),
+[`/file`](/help?name=/file), and [`/raw`](/help?name=/raw) URLs.
+It is common to withhold **Read** capability from low-status visitors
+on private or semi-private repos to prevent them from pulling individual
+elements of the repo over the web one at a time, as someone may do when
+denied the bulk **Clone** capability.
+
+[edoc]: ../embeddeddoc.wiki
+
+
+## <a id="defuser"></a>Default User Name
+
+By default, Fossil assumes your OS user account name is the same as the
+one you use in any Fossil repository. It is the [default for a new
+repository](#new), though you can override this with [the `--admin-user`
+option][auo]. Fossil has other ways of overriding this in other contexts
+such as the `name@` syntax in clone URLs.
+
+It’s simplest to stick with the default; a mismatch can cause problems.
+For example, if you clone someone else’s repo anonymously, turn off
+autosync, and make check-ins to that repository, they will be assigned
+to your OS user name by default. If you later get a login on the remote
+repository under a different name and sync your repo with it, your
+earlier “private” check-ins will get synced to the remote under your OS
+user name!
+
+When such problems occur, you can amend the check-in to hide the
+incorrect name from Fossil reports, but the original values remain in
+the repository [forever][shun]. It is [difficult enough][fos] to fix
+such problems automatically during sync that we are unlikely to ever do
+so.
+
+[auo]: /help?name=new
+[fos]: ./impl.md#filter
+[shun]: ../shunning.wiki
+
+
+
+## <a id="utclone"></a>Cloning the User Table
+
+When cloning over HTTP, the initial user table in the local clone is set
+to its “[new state:](#new)” only one user with Setup capability, named
+after either your OS user account, per the default above, or after the
+user given in the clone URL.
+
+There is one exception: if you clone as a named Setup user, you get a
+complete copy of the user information. This restriction keeps the user
+table private except for the only user allowed to make absolutely
+complete clones of a remote repo, such as for failover or backup
+purposes. Every other user’s clone is missing this and a few other
+items, either for information security or PII privacy reasons.
+
+When cloning with file system paths, `file://` URLs, or over SSH, you
+get a complete clone, including the parent repo’s complete user table.
+
+All of the above applies to [login groups][lg] as well.
+
+
+## <a id="webonly"></a>Caps Affect Web Interfaces Only
+
+Fossil’s user capability system only affects accesses over `http[s]://`
+URLs. This includes clone, sync/push/pull, the [UI pages][wp], and [the
+JSON API][japi]. For everything else, the user caps aren’t consulted at
+all.
+
+The only checks made when working directly with a local repository are
+the operating system’s file system permissions. This should strike you
+as sensible, since if you have read access to the repository file, you
+can do anything you want to that repo DB including giving your user’s
+record the [**Setup**][s] capability, after which Fossil’s user
+capability system is effectively bypassed. (Or, create another Setup
+user, with the same end effect.) If you’re objecting that you need
+*write* access to the DB file to achieve this, realize that you can copy
+a read-only file to another location, giving yourself write access to
+it.
+
+This is why the `fossil ui` command
+gives you Setup permissions within Fossil UI: it can’t usefully prevent
+you from doing anything through the UI since only the local file system
+permissions actually matter, and you can’t start `fossil ui` without
+having at least read access to that file.
+
+What may be more surprising to you is that this is also true when
+working on a *clone* done over a local file path, except that there are
+then two sets of file system permission checks: once to modify the
+working check-out’s repo clone DB file, then again on [sync][sync] with
+the parent DB file. The Fossil capability checks are effectively
+defeated because your user has [**Setup**][s] capability on both sides
+of the sync. Be aware that those file checks do still matter, however:
+Fossil requires write access to a repo DB while cloning from it, so you
+can’t clone from a read-only repo DB file over a local file path.
+
+Even more surprising to you may be the fact that user caps do not affect
+cloning and syncing over SSH! (Not unless you go [out of your way][sshfc]
+to patch around it, at any rate.) When you make a change to such a
+repository, the stock Fossil behavior is that the change first goes to the
+local repo clone where file system
+permissions are all that matter, but then upon sync, the situation is
+effectively the same as when the parent repo is on the local file
+system. The reason behind this is that if you can log into the remote
+system over SSH and that user has the necessary file system permissions
+on that remote repo DB file to allow clone and sync operations, then
+we’re back in the same situation as with local files: there’s no point
+trying to enforce the Fossil user capabilities when you can just modify
+the remote DB directly, so the operation proceeds unimpeded by any user
+capability settings on the remote repo.
+
+Where this gets confusing is that *all* Fossil syncs are done over the
+HTTP protocol, including those done over `file://` and `ssh://` URLs,
+not just those done over `http[s]://` URLs:
+
+* For `ssh://` URLs, Fossil pipes the HTTP conversation through a
+ local SSH client to a remote instance of Fossil running the
+ [`test-http`](/help?name=test-http) command to receive the tunneled
+ HTTP connection. [This interface is intentionally permissionless][sxycap].
+
+* For `file://` URLs — as opposed to plain local file paths —
+ the “sending” Fossil instance writes its side of
+ the HTTP conversation out to a temporary file in the same directory
+ as the local repo clone and then calls itself on the “receiving”
+ repository to read that same HTTP transcript file back in to apply
+ those changes to that repository. Presumably Fossil does this
+ instead of using a pipe to ease portability to Windows.
+
+Despite use of HTTP for these URL types, the fact remains that
+checks for capabilities like [**Read**][o] and [**Write**][i] within the
+HTTP conversation between two Fossil instances only have a useful effect
+when done over an `http[s]://` URL.
+
+[sshfc]: ../server/any/http-over-ssh.md
+[sxycap]: /file?ci=ec5efceb8aac6cb4&name=src/main.c&ln=2748-2752
+
+
+## <a id="pubpg"></a>Public Pages
+
+In Admin → Access, there is an option for giving a list of [globs][glob]
+to name URLs which get treated as if the visitor had [the default cap
+set](#defcap). For example, you could take the [**Read**][o] capability
+away from the “nobody” user category, who has it by default, to prevent
+users without logins from pulling down your repository contents one
+artifact at a time, yet give those users the ability to read the project
+documentation by setting the glob to match your [embedded
+documentation][edoc]’s URL root.
+
+
+## <a id="defcap"></a>Default User Capability Set
+
+In Admin → Access, you can define a default user capability set, which
+is used as:
+
+1. the default caps for users newly created by an Admin or Setup user
+2. the default caps for self-registered users, an option in that same UI
+3. the effective caps for URIs considered [public pages](#pubpg)
+
+This defaults to [**Reader**][u].
+
+
+<!-- add padding so anchor links always scroll ref’d section to top -->
+<div style="height: 75em"></div>
+
+[ref]: ./ref.html
+
+[a]: ./ref.html#a
+[b]: ./ref.html#b
+[c]: ./ref.html#c
+[d]: ./ref.html#d
+[e]: ./ref.html#e
+[f]: ./ref.html#f
+[g]: ./ref.html#g
+[h]: ./ref.html#h
+[i]: ./ref.html#i
+[j]: ./ref.html#j
+[k]: ./ref.html#k
+[l]: ./ref.html#l
+[m]: ./ref.html#m
+[n]: ./ref.html#n
+[o]: ./ref.html#o
+[p]: ./ref.html#p
+[q]: ./ref.html#q
+[r]: ./ref.html#r
+[s]: ./ref.html#s
+[t]: ./ref.html#t
+[u]: ./ref.html#u
+[v]: ./ref.html#v
+[w]: ./ref.html#w
+[x]: ./ref.html#x
+[y]: ./ref.html#y
+[z]: ./ref.html#z
+
+[2]: ./ref.html#2
+[3]: ./ref.html#3
+[4]: ./ref.html#4
+[5]: ./ref.html#5
+[6]: ./ref.html#6
+[7]: ./ref.html#7
+
+[glob]: https://en.wikipedia.org/wiki/Glob_(programming)
+[japi]: https://docs.google.com/document/d/1fXViveNhDbiXgCuE7QDXQOKeFzf2qNUkBEgiUvoqFN4/view#heading=h.6k0k5plm18p1
+[sp]: ../sync.wiki
+[sync]: /help?name=sync
+[wp]: /help#webpages
diff --git a/www/caps/login-groups.md b/www/caps/login-groups.md
new file mode 100644
index 0000000..7cca2d7
--- /dev/null
+++ b/www/caps/login-groups.md
@@ -0,0 +1,128 @@
+# Login Groups
+
+The Admin → Login-Groups UI feature and its corresponding [`login-group`
+command][lg] solve a common problem with Fossil: you’ve created multiple
+repositories that some subset of users need access to, and you
+don’t want to redundantly administer the user credentials for each
+repository.
+
+
+## Restrictions
+
+This feature ties changes to the “`user`” table in one repo to that in
+one or more other repos, keyed by the user’s name. The interactions are
+non-obvious because although the goal is for the end result to “just
+work,” there are practical security and administration matters that
+complicate things:
+
+1. Login group handling only works between joined repositories for the
+ subset of users with the same name.
+
+1. If you’re logged in on one repo in a group, any other repo in that
+ group that has a matching user record will accept your valid login.
+
+1. When you set up a login group between two repos, the user tables
+ aren’t merged, so even though you may have users that appear in
+ both, they will retain their initial passwords, credentials, and so
+ forth.
+
+1. The same is true after the login group is created: changes you make
+ to the user table in one repo in the group only propagate to the
+ other repos in the group when you check the “Apply changes to all
+ repositories“ box in the “Scope” section of the user edit screen.
+ Otherwise, user changes remain local to the repo you made them on.
+
+1. Login groups only affect [the HTTP interfaces][wo]. Contrast things
+ like `ssh://` clones, where unless you [go out of your way][sh] to
+ force them to run over one of the HTTP interfaces that pays
+ attention to Fossil’s RBAC system, login groups aren’t consulted.
+
+
+## Interactions
+
+These restrictions combine in subtle and interesting ways. Examples:
+
+* **#1 and #2**: If you are logged into repo C as “charlie” and then
+ try to visit joined repo A where “charlie” doesn’t exist, your valid
+ login on C won’t get you into A.
+
+* **#2 and #3**: If “alice” exists in both of these same repos,
+ logging in on A gets her into C, but if she has different user
+ capabilities on each from the time before the two repos joined the
+ login group, her caps on A don’t apply to C, nor vice versa.
+
+ Let us say F is a forum-only repo, and W is a wiki-only repo, and
+ that Alice has forum-posting rights on F and wiki-editing rights on
+ W. If both repos are joined by a login group, Alice can log in on F
+ and then access W without logging in on it separately, but she
+ cannot then post a forum message on W even though she could on F.
+
+* **#3 and #4**: If you change the caps for user “alice” on one repo
+ in a group and tell Fossil to apply the changes to all repos in the
+ group, the new caps will *overwrite* those on the other repos, not
+ merge with them.
+
+ To extend the practical example from the prior point, let us say you
+ wish to grant Alice the “write unversioned” capability on both F and
+ W. If you check that single user cap box on F plus the “apply to
+ all” option, then “Apply Changes,” she will end up with forum +
+ unversioned caps on repo W, losing her wiki-editing caps in the
+ process.
+
+ If you want user caps to differ on each repo, you must administer
+ them separately even if there is a common subset of caps between all
+ repos in the group for that user. Remember: selecting the “apply to
+ all” box calls for an overwrite operation, not a merge.
+
+* **#4 and #1**: If you make a change to an existing user “bob” in
+ repo B and select the “apply to all” option, it will only affect
+ other repos in the group that have a user “bob” configured.
+
+ But, if you are instead creating user “bob” for the first time and
+ select that option, that user *will* be created in all repos. The
+ same is true of user deletion: that destructive action will
+ propagate through the group if you request it.
+
+* **#5 and #1**: If you have a user “daisy” on both repos A and B in a
+ login group, logging in over the web to A doesn’t let you push
+ changes into B over SSH. Without the workaround linked above, SSH
+ only pays attention to the operating system’s user authentication
+ system, not Fossil’s.
+
+ Inversely, if Daisy successfully logs in over SSH to repo B, she
+ gains no access to any of the other repos in that group. She needs
+ at least one valid login over HTTP to one of the group’s repos.
+
+
+## Discussion
+
+The end result of all of this is that you can have a subset of users
+with credentials only on repo A, a different subset only on B, and a
+third subset common to both. The only thing selecting which case applies
+is restriction #1 above.
+
+Login groups have names. A repo can be in only one of these named login
+groups at a time.
+
+Trust in login groups is transitive within a single server. Consider
+this sequence:
+
+ $ cd /path/to/A/checkout
+ $ fossil login-group join --name G ~/museum/B.fossil
+ $ cd /path/to/C/checkout
+ $ fossil login-group join ~/museum/B.fossil
+
+That creates login group G joining repo A to B, then joins C to B.
+Although we didn’t explicitly tie C to A, a successful login on C gets
+you into both A and B, within the restrictions set out above.
+
+Changes are transitive in the same way, provided you check that “apply
+to all” box on the user edit screen.
+
+[lg]: /help/login-group
+[sh]: ../server/any/http-over-ssh.md
+[wo]: ./index.md#webonly
+
+-----
+
+*[Back to Administering User Capabilities](./)*
diff --git a/www/caps/ref.html b/www/caps/ref.html
new file mode 100644
index 0000000..9c218ff
--- /dev/null
+++ b/www/caps/ref.html
@@ -0,0 +1,454 @@
+<div class='fossil-doc' data-title="User Capability Reference">
+
+<style type="text/css">
+ p#backlink {
+ /* Make empty space below the table so hyperlinks to named anchors
+ near the bottom of the table still scroll that row to the top of
+ the user's browser, even on tall screens. */
+ margin-bottom: 75em;
+ }
+
+ tr > th {
+ background-color: #e8e8e8;
+ vertical-align: top;
+ }
+ body.fossil-dark-style tr > th {
+ color: #000;
+ opacity: 0.85;
+ }
+
+ tr.cols th {
+ white-space: nowrap;
+ }
+
+ td, th {
+ padding: 0.4em;
+ }
+</style>
+
+<p>Here we document each currently-defined user capability character in
+more detail than the brief summary on the <a
+href="/setup_ucap_list">“key” page</a> in the Fossil user editor. Each
+row gives the capability letter used in the Fossil user editor followed
+by the C code’s name for that cap within the <tt>FossilUserPerms</tt>
+object, so you can use this reference both from the UI down and from the
+C code up.</p>
+
+<p>The <a href="https://en.wikipedia.org/wiki/Mnemonic">mnemonics</a>
+given here vary from obviously-correct to <i>post facto</i>
+rationalizations to the outright fanciful. To <a
+href="./impl.md#choices">some extent</a>, this is unavoidable.</p>
+
+
+<h2>Reference</h2>
+
+<table>
+ <tr class="cols">
+ <th>?</th>
+ <th>Name</th>
+ <th style="text-align: left">Description</th>
+ </tr>
+
+ <tr id="a">
+ <th>a</th>
+ <th>Admin</th>
+ <td>
+ Admin users have <em>all</em> of the capabilities below except for
+ <a href="#s">setup</a>, <a herf="#x">Private</a>, and <a href="#y">WrUnver</a>.
+ See <a href="admin-v-setup.md">Admin vs. Setup</a> for a more
+ nuanced discussion. Mnemonic: <b>a</b>dministrate.
+ </td>
+ </tr>
+
+ <tr id="b">
+ <th>b</th>
+ <th>Attach</th>
+ <td>
+ Add attachments to wiki articles, technotes, or tickets.
+ Mnemonics: <b>b</b>ind, <b>b</b>utton, <b>b</b>ond, or <b>b</b>olt.
+ See also: <a href='#B'>B</a>.
+ </td>
+ </tr>
+
+ <tr id="c">
+ <th>c</th>
+ <th>ApndTkt</th>
+ <td>
+ Append comments to existing tickets. Mnemonic: <b>c</b>omment.
+ </td>
+ </tr>
+
+ <tr id="d">
+ <th>d</th>
+ <th>n/a</th>
+ <td>
+ Legacy capability letter from Fossil's forebear <a
+ href="http://cvstrac.org/">CVSTrac</a>, which has no useful
+ meaning in Fossil due to the nature of its durable Merkle tree design.
+ We recommend that you remove it in case we
+ ever reuse this letter for another purpose. See <a
+ href="https://fossil-scm.org/forum/forumpost/43c78f4bef">this
+ post</a> for details.
+ </td>
+ </tr>
+
+ <tr id="e">
+ <th>e</th>
+ <th>RdAddr</th>
+ <td>
+ View <a
+ href="https://en.wikipedia.org/wiki/Personal_data">personal
+ identifying information</a> (PII) about other users such as email
+ addresses. Mnemonics: show <b>e</b>mail addresses; or
+ <b>E</b>urope, home of <a
+ href="https://en.wikipedia.org/wiki/General_Data_Protection_Regulation">GDPR</a>.
+ </td>
+ </tr>
+
+ <tr id="f">
+ <th>f</th>
+ <th>NewWiki</th>
+ <td>
+ Create new wiki articles. Mnemonic: <b>f</b>ast, English
+ translation of the Hawaiian word <a
+ href="https://en.wikipedia.org/wiki/History_of_wikis#WikiWikiWeb,_the_first_wiki"><i>wiki</i></a>.
+ </td>
+ </tr>
+
+ <tr id="g">
+ <th>g</th>
+ <th>Clone</th>
+ <td>
+ Clone the repository. Note that this is distinct from <a
+ href="#o">check-out capability, <b>o</b></a>; and that upon cloning
+ not just files, but also tickets, wikis, technotes and forum posts
+ are tranferred. Mnemonic: <b>g</b>et.
+ </td>
+ </tr>
+
+ <tr id="h">
+ <th>h</th>
+ <th>Hyperlink</th>
+ <td>
+ Get hyperlinks in generated HTML which link you to other parts of
+ the repository. This capability exists so we can deny it to the
+ “nobody” category, to <a href="../antibot.wiki">prevent bots from
+ wandering around aimlessly</a> in the site’s hyperlink web, <a
+ href="../loadmgmt.md">chewing up server resources</a> to little
+ good purpose. Mnemonic: <b>h</b>yperlink.
+ </td>
+ </tr>
+
+ <tr id="i">
+ <th>i</th>
+ <th>Write</th>
+ <td>
+ Check changes into the repository. Note that a lack of this
+ capability does not prevent you from checking changes into your
+ local clone, only from syncing those changes up to the parent
+ repo, and then <a href="./basics.md#webonly">only over HTTP</a>.
+ Also note that not just files, but also tickets, wikis, technotes
+ and forum posts will be accepted from clones upon syncronization.
+ Granting this capability also grants <b>o (Read)</b> Mnemonics:
+ <b>i</b>nput, check <b>i</b>n changes.
+ </td>
+ </tr>
+
+ <tr id="j">
+ <th>j</th>
+ <th>RdWiki</th>
+ <td>
+ View wiki articles. Mnemonic: in<b>j</b>est page content. (All
+ right, you critics, you do better, then.)
+ </td>
+ </tr>
+
+ <tr id="k">
+ <th>k</th>
+ <th>WrWiki</th>
+ <td>
+ Edit wiki articles. Granting this capability also grants <a
+ href="#j"><b>RdWiki</b></a> and <a href="#m"><b>ApndWiki</b></a>,
+ but it does <em>not</em> grant <a href="#f"><b>NewWiki</b></a>!
+ Mnemonic: <b>k</b>ontribute.
+ </td>
+ </tr>
+
+ <tr id="l">
+ <th>l</th>
+ <th>ModWiki</th>
+ <td>
+ Moderate <a href="#m">wiki article appends</a>. Appends do not get
+ saved permanently to the receiving repo’s block chain until <a
+ href="#s">Setup</a> or someone with this cap approves it.
+ Mnemonic: a<b>l</b>low.
+ </td>
+ </tr>
+
+ <tr id="m">
+ <th>m</th>
+ <th>ApndWiki</th>
+ <td>
+ Append content to existing wiki articles. Mnemonic: a<b>m</b>end
+ wiki
+ </td>
+ </tr>
+
+ <tr id="n">
+ <th>n</th>
+ <th>NewTkt</th>
+ <td>
+ File new tickets. Mnemonic: <b>n</b>ew ticket.
+ </td>
+ </tr>
+
+ <tr id="o">
+ <th>o</th>
+ <th>Read</th>
+ <td>
+ Read content and history of files from a remote Fossil instance over
+ HTTP. See <a href="index.md#read-v-clone">Reading vs.
+ Cloning</a>. Mnemonic: check <b>o</b>ut remote repo contents.
+ </td>
+ </tr>
+
+ <tr id="p">
+ <th>p</th>
+ <th>Password</th>
+ <td>
+ Change one’s own password. Mnemonic: <b>p</b>assword.
+ </td>
+ </tr>
+
+ <tr id="q">
+ <th>q</th>
+ <th>ModTkt</th>
+ <td>
+ Moderate tickets: delete comments appended to tickets. Mnemonic:
+ <b>q</b>uash noise commentary.
+ </td>
+ </tr>
+
+ <tr id="r">
+ <th>r</th>
+ <th>RdTkt</th>
+ <td>
+ View existing tickets. Mnemonic: <b>r</b>ead tickets.
+ </td>
+ </tr>
+
+ <tr id="s">
+ <th>s</th>
+ <th>Setup</th>
+ <td>
+ The <a href="./admin-v-setup.md#apsu">all-powerful Setup user</a>.
+ Mnemonics: <b>s</b>etup or <b>s</b>uperuser.
+ </td>
+ </tr>
+
+ <tr id="t">
+ <th>t</th>
+ <th>TktFmt</th>
+ <td>
+ Create new ticket report formats. Note that although this allows
+ the user to provide SQL code to be run in the server’s context,
+ and this capability is given to the untrusted “anonymous” user
+ category by default, this is a safe capability to give to users
+ because it is internally restricted to read-only queries on the
+ tickets table only. (This restriction is done with an SQLite
+ authorization hook, not by any method so weak as SQL text
+ filtering.) Mnemonic: new <b>t</b>icket report.
+ </td>
+ </tr>
+
+ <tr id="u">
+ <th>u</th>
+ <th>n/a</th>
+ <td>
+ Inherit all capabilities of the “reader” user category; does not
+ have a dedicated flag internally within Fossil. Mnemonic:
+ <a href="./index.md#ucat"><b>u</b>ser</a>
+ </td>
+ </tr>
+
+ <tr id="v">
+ <th>v</th>
+ <th>n/a</th>
+ <td>
+ Inherit all capabilities of the “developer” user category; does
+ not have a dedicated flag internally within Fossil. Mnemonic:
+ de<b>v</b>eloper.
+ </td>
+ </tr>
+
+ <tr id="w">
+ <th>w</th>
+ <th>WrTkt</th>
+ <td>
+ Edit existing tickets. Granting this capability also grants <a
+ href="#r"><b>RdTkt</b></a>, <a href="#c"><b>ApndTkt</b></a>, and
+ <a href="#n"><b>NewTkt</b></a>. Mnemonic: <b>w</b>rite to ticket.
+ </td>
+ </tr>
+
+ <tr id="x">
+ <th>x</th>
+ <th>Private</th>
+ <td>
+ Push or pull <a href="../private.wiki">private branches</a>.
+ Mnemonic: e<b>x</b>clusivity; “x” connotes unknown material in
+ many Western languages due to its <a
+ href="https://en.wikipedia.org/wiki/La_Géométrie#The_text">traditional
+ use in mathematics</a>.
+ </td>
+ </tr>
+
+ <tr id="y">
+ <th>y</th>
+ <th>WrUnver</th>
+ <td>
+ Push <a href="../unvers.wiki">unversioned content</a>. Mnemonic:
+ <b>y</b>ield, <a href="https://en.wiktionary.org/wiki/yield">sense
+ 4</a>: “hand over.”
+ </td>
+ </tr>
+
+ <tr id="z">
+ <th>z</th>
+ <th>Zip</th>
+ <td>
+ Pull archives of particular repository versions via <a
+ href="/help/www/zip"><tt>/zip</tt></a>, <a
+ href="/help/www/tarball"><tt>/tarball</tt></a>, and <a
+ href="/help/www/sqlar"><tt>/sqlar</tt></a> URLs. This is an
+ expensive capability to grant, because creating such archives can
+ put a large load on <a href="../server/">a Fossil server</a> which
+ you may then need to <a href="../loadmgmt.md">manage</a>.
+ Mnemonic: <b>z</b>ip file download.
+ </td>
+ </tr>
+
+ <tr id="2">
+ <th>2</th>
+ <th>RdForum</th>
+ <td>
+ Read <a href="../forum.wiki">forum posts</a> by other users.
+ Mnemonic: from thee <b>2</b> me.
+ </td>
+ </tr>
+
+ <tr id="3">
+ <th>3</th>
+ <th>WrForum</th>
+ <td>
+ Create new forum threads, reply to threads created by others, and
+ edit one’s own posts. New posts are <a
+ href="../forum.wiki#moderation">held for moderation</a> and do
+ not appear in repo clones or syncs. Granting this capability also
+ grants <a href="#2"><b>RdForum</b></a>. Mnemonic: post for
+ <b>3</b> audiences: me, <a href="#5">the mods</a>, and <a
+ href="https://en.wikipedia.org/wiki/The_Man">the Man</a>.
+ </td>
+ </tr>
+
+ <tr id="4">
+ <th>4</th>
+ <th>WrTForum</th>
+ <td>
+ Extends <a href="#3"><b>WrForum</b></a>, bypassing the moderation
+ and sync restrictions. Mnemonic: post <b>4</b> immediate release.
+ </td>
+ </tr>
+
+ <tr id="5">
+ <th>5</th>
+ <th>ModForum</th>
+ <td>
+ <a href="../forum.wiki#moderation">Moderate forum posts</a>.
+ Granting this capability also grants <a
+ href="#4"><b>WrTForum</b></a> and <a href="#2"><b>RdForum</b></a>,
+ so a user with this cap never has to moderate their own posts.
+ Mnemonic: “May I have <b>5</b> seconds of your time, honored
+ Gatekeeper?”
+ </td>
+ </tr>
+
+ <tr id="6">
+ <th>6</th>
+ <th>AdminForum</th>
+ <td>
+ Users with this capability see a checkbox on unmoderated forum
+ posts labeled “Trust user X so that future posts by user X do not
+ require moderation.” Checking that box and then clicking the
+ moderator-only “Approve” button on that post grants <a
+ href="#4"><b>WrTForum</b></a> capability to that post’s author.
+ There is currently no UI for a user with this cap to
+ <em>revoke</em> trust from a user once it is granted; only <a
+ href="#a"><b>Admin</b></a> and <a href="#s"><b>Setup</b></a> can
+ currently revoke granted caps. Granting this capability also
+ grants <a href="#5"><b>ModForum</b></a> and those it in turn
+ grants. Mnemonic: “I’m <b>6</b> [sick] of hitting Approve on your
+ posts!”
+ </td>
+ </tr>
+
+ <tr id="7">
+ <th>7</th>
+ <th>EmailAlert</th>
+ <td>
+ User can sign up for <a href="../alerts.md">email alerts</a>.
+ Mnemonic: <a href="https://en.wikipedia.org/wiki/Heaven_Can_Wait">Seven can
+ wait</a>, I’ve got email to read now.
+ </td>
+ </tr>
+
+ <tr id="A">
+ <th>A</th>
+ <th>Announce</th>
+ <td>
+ Send email announcements to users <a href="#7">signed up to
+ receive them</a>. Mnemonic: <b>a</b>nnounce.
+ </td>
+ </tr>
+
+ <tr id="B">
+ <th>B</th>
+ <th>Attach to Forum</th>
+ <td>
+ Add attachments to forum posts. See also: <a href='#b'>b</a>.
+ </td>
+ </tr>
+
+ <tr id="C">
+ <th>C</th>
+ <th>Chat</th>
+ <td>
+ Allow access to the <tt>/chat</tt> room.
+ </td>
+ </tr>
+
+ <tr id="D">
+ <th>D</th>
+ <th>Debug</th>
+ <td>
+ Enable debugging features. Mnemonic: <b>d</b>ebug.
+ </td>
+ </tr>
+
+ <tr id="L">
+ <th>L</th>
+ <th>Is-logged-in</th>
+ <td>
+ This is not a real capability, but is used in certain capability
+ checks, e.g. via <a href="../th1.md#capexpr">capexpr</a>. It
+ resolves to true if the current user is logged in.
+ Mnemonic: <b>L</b>ogged in.
+ </td>
+ </tr>
+
+</table>
+
+<hr/>
+
+<p id="backlink"><a href="./"><em>Back to Administering User
+Capabilities</em></a></p>