Fossil SCM

fossil-scm / www / caps / index.md
Source Blame History 405 lines
23b91f3… wyoung 1 # Administering User Capabilities (a.k.a. Permissions)
779ddef… wyoung 2
779ddef… wyoung 3 Fossil includes a powerful [role-based access control system][rbac]
23b91f3… wyoung 4 which affects which users have which capabilities(^Some parts of the
23b91f3… wyoung 5 Fossil code call these “permissions” instead, but since there is [a
23b91f3… wyoung 6 clear and present risk of confusion](#webonly) with operating system
23b91f3… wyoung 7 level file permissions in this context, we avoid using that term for
23b91f3… wyoung 8 Fossil’s RBAC capability flags in these pages.) within a given
23b91f3… wyoung 9 [served][svr] Fossil repository. We call this the “caps” system for
23b91f3… wyoung 10 short.
779ddef… wyoung 11
779ddef… wyoung 12 Fossil stores a user’s caps as an unordered string of ASCII characters,
779ddef… wyoung 13 one capability per, [currently](./impl.md#choices) limited to
779ddef… wyoung 14 [alphanumerics][an]. Caps are case-sensitive: “**A**” and “**a**” are
779ddef… wyoung 15 different user capabilities.
779ddef… wyoung 16
779ddef… wyoung 17 This is a complex topic, so some sub-topics have their own documents:
779ddef… wyoung 18
779ddef… wyoung 19 1. [Login Groups][lg]
779ddef… wyoung 20 2. [Implementation Details](./impl.md)
779ddef… wyoung 21 3. [User Capability Reference](./ref.html)
779ddef… wyoung 22
b45da25… drh 23 [an]: https://en.wikipedia.org/wiki/Alphanumeric
779ddef… wyoung 24 [avs]: ./admin-v-setup.md
779ddef… wyoung 25 [lg]: ./login-groups.md
779ddef… wyoung 26 [rbac]: https://en.wikipedia.org/wiki/Role-based_access_control
779ddef… wyoung 27
779ddef… wyoung 28
93cee1f… wyoung 29 ## <a id="ucat"></a>User Categories
779ddef… wyoung 30
779ddef… wyoung 31 Before we explain individual user capabilities and their proper
779ddef… wyoung 32 administration, we want to talk about an oft-overlooked and
779ddef… wyoung 33 misunderstood feature of Fossil: user categories.
779ddef… wyoung 34
779ddef… wyoung 35 Fossil defines four user categories. Two of these apply based on the
779ddef… wyoung 36 user’s login status: **nobody** and **anonymous**. The other two act
779ddef… wyoung 37 like Unix or LDAP user groups: **reader** and **developer**. Because we
779ddef… wyoung 38 use the word “group” for [another purpose][lg] in Fossil, we will
779ddef… wyoung 39 avoid using it that way again in this document. The correct term in
779ddef… wyoung 40 Fossil is “category.”
779ddef… wyoung 41
779ddef… wyoung 42 Fossil user categories give you a way to define capability sets for four
779ddef… wyoung 43 hard-coded situations within the Fossil C source code. Logically
779ddef… wyoung 44 speaking:
779ddef… wyoung 45
779ddef… wyoung 46 > *(developer* &or; *reader)* &ge; *anonymous* &ge; *nobody*
779ddef… wyoung 47
779ddef… wyoung 48 When a user visits a [served Fossil repository][svr] via its web UI,
779ddef… wyoung 49 they initially get the capabilities of the “nobody” user category. This
779ddef… wyoung 50 category would be better named “everybody” because it applies whether
779ddef… wyoung 51 you’re logged in or not.
779ddef… wyoung 52
779ddef… wyoung 53 When a user logs in as “anonymous” via [`/login`](/help?name=/login) they
779ddef… wyoung 54 get all of the “nobody” category’s caps plus those assigned to the
779ddef… wyoung 55 “anonymous” user category. It would be better named “user” because it
779ddef… wyoung 56 affects all logged-in users, not just those logged in via Fossil’s
779ddef… wyoung 57 anonymous user feature.
779ddef… wyoung 58
779ddef… wyoung 59 When a user with either the “reader” ([**u**][u]) or “developer”
779ddef… wyoung 60 ([**v**][v]) capability letter logs in, they get their [individual user
779ddef… wyoung 61 caps](#ucap) plus those assigned to this special user category. They
779ddef… wyoung 62 also get those assigned to the “anonymous” and “nobody” categories.
779ddef… wyoung 63
779ddef… wyoung 64 Because “developer” users do not automatically inherit “reader” caps,
779ddef… wyoung 65 it is standard practice to give both letters to your “developer” users:
779ddef… wyoung 66 **uv**. You could instead just assign cap **u** to the “developer”
779ddef… wyoung 67 category.
779ddef… wyoung 68
779ddef… wyoung 69 Fossil shows how these capabilities apply hierarchically in the user
779ddef… wyoung 70 editing screen (Admin → Users → name) with the `[N]` `[A]` `[D]` `[R]`
779ddef… wyoung 71 tags next to each capability check box. If a user gets a capability from
779ddef… wyoung 72 one of the user categories already assigned to it, there is no value in
779ddef… wyoung 73 redundantly assigning that same cap to the user explicitly. For example,
1274054… drh 74 with the default **ei** cap set for the “developer” category, the cap
1274054… drh 75 set **ve** is redundant because **v** grants **ei**, which includes
779ddef… wyoung 76 **e**.
779ddef… wyoung 77
779ddef… wyoung 78 We suggest that you lean heavily on these fixed user categories when
779ddef… wyoung 79 setting up new users. Ideally, your users will group neatly into one of
779ddef… wyoung 80 the predefined categories, but if not, you might be able to shoehorn
779ddef… wyoung 81 them into our fixed scheme. For example, the administrator of a
779ddef… wyoung 82 wiki-only Fossil repo for non-developers could treat the “developer”
779ddef… wyoung 83 user category as if it were called “author,” and a forum-only repo could
779ddef… wyoung 84 treat the same category as if it were called “member.”
779ddef… wyoung 85
779ddef… wyoung 86 There is currently no way to define custom user categories.
779ddef… wyoung 87
779ddef… wyoung 88 [svr]: ../server/
779ddef… wyoung 89
779ddef… wyoung 90
93cee1f… wyoung 91 ## <a id="ucap"></a>Individual User Capabilities
779ddef… wyoung 92
779ddef… wyoung 93 When one or more users need to be different from the basic capabilities
779ddef… wyoung 94 defined in user categories, you can assign caps to individual users. You
779ddef… wyoung 95 may want to have the [cap reference][ref] open when doing such work.
779ddef… wyoung 96
779ddef… wyoung 97 It is useful at this time to expand on the logical
779ddef… wyoung 98 expression [above](#cat), which covered only the four fixed user categories.
779ddef… wyoung 99 When we bring the individual user capabilities into it, the complete
779ddef… wyoung 100 expression of the way Fossil implements user power becomes:
779ddef… wyoung 101
779ddef… wyoung 102 > *setup* &ge; *admin* &ge; *moderator* &ge; *(developer* &or; *reader)* &ge; *[subscriber]* &ge; *anonymous* &ge; *nobody*
779ddef… wyoung 103
779ddef… wyoung 104 The two additions at the top are clear: [setup is all-powerful][apsu],
779ddef… wyoung 105 and since admin users have [all capabilities][ref] except for Setup
779ddef… wyoung 106 capability, they are [subordinate only to the setup user(s)][avsp].
779ddef… wyoung 107
779ddef… wyoung 108 The moderator insertion could go anywhere from where it’s shown now down
779ddef… wyoung 109 to above the “anonymous” level, depending on what other caps you give to
779ddef… wyoung 110 your moderators. Also, there is not just one type of moderator: Fossil
779ddef… wyoung 111 has [wiki][l], [ticket][q], and [forum][5] moderators, each
779ddef… wyoung 112 independent of the others. Usually your moderators are fairly
779ddef… wyoung 113 high-status users, with developer capabilities or higher, but Fossil
779ddef… wyoung 114 does allow the creation of low-status moderators.
779ddef… wyoung 115
779ddef… wyoung 116 The placement of “subscriber” in that hierarchy is for the
779ddef… wyoung 117 sort of subscriber who has registered an account on the repository
779ddef… wyoung 118 purely to [receive email alerts and announcements][7]. Users with
779ddef… wyoung 119 additional caps can also be subscribers, but not all users *are* in fact
779ddef… wyoung 120 subscribers, which is why we show it in square brackets. (See [Users vs
779ddef… wyoung 121 Subscribers](../alerts.md#uvs).)
779ddef… wyoung 122
779ddef… wyoung 123 [apsu]: ./admin-v-setup.md#apsu
779ddef… wyoung 124 [avsp]: ./admin-v-setup.md#philosophy
779ddef… wyoung 125
779ddef… wyoung 126
93cee1f… wyoung 127 ## <a id="new"></a>New Repository Defaults
779ddef… wyoung 128
779ddef… wyoung 129 Fossil creates one user account in new repos, which is named after your
779ddef… wyoung 130 OS user name [by default](#defuser).
779ddef… wyoung 131
779ddef… wyoung 132 Fossil gives the initial repository user the [all-powerful Setup
779ddef… wyoung 133 capability][apsu].
779ddef… wyoung 134
779ddef… wyoung 135 Users who visit a [served repository][svr] without logging in get the
779ddef… wyoung 136 “nobody” user category’s caps which default to
779ddef… wyoung 137 **[g][g][j][j][o][o][r][r][z][z]**: clone the repo, read the wiki,
779ddef… wyoung 138 check-out files via the web UI, view tickets, and pull version archives.
779ddef… wyoung 139 This default is suited to random passers-by on a typical FOSS project’s
779ddef… wyoung 140 public web site and its code repository.
779ddef… wyoung 141
779ddef… wyoung 142 Users who [prove they are not a bot][bot] by logging in — even if only
779ddef… wyoung 143 as “anonymous” — get the “nobody” capability set plus
779ddef… wyoung 144 **[h][h][m][m][n][n][c][c]**: see internal hyperlinks, append to
779ddef… wyoung 145 existing wiki articles, file new tickets, and comment on existing
779ddef… wyoung 146 tickets. We chose these additional capabilities as those we don’t want
779ddef… wyoung 147 bots to have, but which a typical small FOSS project would be happy to
779ddef… wyoung 148 give anonymous humans visiting the project site.
779ddef… wyoung 149
779ddef… wyoung 150 The “reader” user category is typically assigned to users who want to be
779ddef… wyoung 151 identified within the repository but who primarily have a passive role
779ddef… wyoung 152 in the project. The default capability set on a Fossil repo adds
779ddef… wyoung 153 **[k][k][p][p][t][t][w][w]** caps to those granted by “nobody” and
779ddef… wyoung 154 “anonymous”. This category is not well-named, because the default caps
779ddef… wyoung 155 are all about modifying repository content: edit existing wiki pages,
779ddef… wyoung 156 change one’s own password, create new ticket report formats, and modify
779ddef… wyoung 157 existing tickets. This category would be better named “participant”.
779ddef… wyoung 158
779ddef… wyoung 159 Those in the “developer” category get the “nobody” and “anonymous” cap
1274054… drh 160 sets plus **[e][e][i][i]**: view
1274054… drh 161 sensitive user material and check in changes.
779ddef… wyoung 162
779ddef… wyoung 163 [bot]: ../antibot.wiki
779ddef… wyoung 164
779ddef… wyoung 165
93cee1f… wyoung 166 ## <a id="pvt"></a>Consequences of Taking a Repository Private
779ddef… wyoung 167
779ddef… wyoung 168 When you click Admin → Security-Audit → “Take it private,” one of the
779ddef… wyoung 169 things it does is set the user capabilities for the “nobody” and
779ddef… wyoung 170 “anonymous” user categories to blank, so that users who haven’t logged
779ddef… wyoung 171 in can’t even see your project’s home page, and the option to log in as
779ddef… wyoung 172 “anonymous” isn’t even offered. Until you log in with a user name, all
779ddef… wyoung 173 you see is the repository’s skin and those few UI elements that work
779ddef… wyoung 174 without any user capability checks at all, such as the “Login” link.
779ddef… wyoung 175
779ddef… wyoung 176 Beware: Fossil does not reassign the capabilities these users had to
779ddef… wyoung 177 other users or to the “reader” or “developer” user category! All users
779ddef… wyoung 178 except those with Setup capability will lose all capabilities they
779ddef… wyoung 179 inherited from “nobody” and “anonymous” categories. Setup is the [lone
779ddef… wyoung 180 exception][apsu].
779ddef… wyoung 181
779ddef… wyoung 182 If you will have non-Setup users in your private repo, you should parcel
779ddef… wyoung 183 out some subset of the capability set the “nobody” and “anonymous”
779ddef… wyoung 184 categories had to other categories or to individual users first.
779ddef… wyoung 185
779ddef… wyoung 186
93cee1f… wyoung 187 ## <a id="read-v-clone"></a>Reading vs. Cloning
779ddef… wyoung 188
779ddef… wyoung 189 Fossil has two capabilities that are often confused:
779ddef… wyoung 190 [**Read**](./ref.html#o) and [**Clone**](./ref.html#g).
779ddef… wyoung 191
779ddef… wyoung 192 The **Read** capability has nothing to do with reading data from a local
779ddef… wyoung 193 repository, because [caps affect Fossil’s web interfaces
779ddef… wyoung 194 only](#webonly). Once you’ve cloned a remote repository to your local
779ddef… wyoung 195 machine, you can do any reading you want on that repository irrespective
779ddef… wyoung 196 of whether your local user within that repo has <b>Read</b> capability.
779ddef… wyoung 197 The repo clone is completely under your user’s power at that point,
779ddef… wyoung 198 affected only by OS file permissions and such. If you need to prevent
779ddef… wyoung 199 that, you want to deny **Clone** capability instead.
779ddef… wyoung 200
779ddef… wyoung 201 Withholding the **Read** capability has a different effect: it
6e5337e… george 202 prevents a web client from viewing [embedded documentation][edoc],
6e5337e… george 203 using [the file browser](/help?name=/dir),
6e5337e… george 204 exploring the [history](/help?name=/timeline) of check-ins,
6e5337e… george 205 and pulling file content via the [`/artifact`](/help?name=/artifact),
6e5337e… george 206 [`/file`](/help?name=/file), and [`/raw`](/help?name=/raw) URLs.
6e5337e… george 207 It is common to withhold **Read** capability from low-status visitors
779ddef… wyoung 208 on private or semi-private repos to prevent them from pulling individual
779ddef… wyoung 209 elements of the repo over the web one at a time, as someone may do when
779ddef… wyoung 210 denied the bulk **Clone** capability.
779ddef… wyoung 211
779ddef… wyoung 212 [edoc]: ../embeddeddoc.wiki
779ddef… wyoung 213
779ddef… wyoung 214
93cee1f… wyoung 215 ## <a id="defuser"></a>Default User Name
779ddef… wyoung 216
779ddef… wyoung 217 By default, Fossil assumes your OS user account name is the same as the
779ddef… wyoung 218 one you use in any Fossil repository. It is the [default for a new
779ddef… wyoung 219 repository](#new), though you can override this with [the `--admin-user`
779ddef… wyoung 220 option][auo]. Fossil has other ways of overriding this in other contexts
779ddef… wyoung 221 such as the `name@` syntax in clone URLs.
779ddef… wyoung 222
779ddef… wyoung 223 It’s simplest to stick with the default; a mismatch can cause problems.
779ddef… wyoung 224 For example, if you clone someone else’s repo anonymously, turn off
779ddef… wyoung 225 autosync, and make check-ins to that repository, they will be assigned
779ddef… wyoung 226 to your OS user name by default. If you later get a login on the remote
779ddef… wyoung 227 repository under a different name and sync your repo with it, your
779ddef… wyoung 228 earlier “private” check-ins will get synced to the remote under your OS
779ddef… wyoung 229 user name!
779ddef… wyoung 230
779ddef… wyoung 231 When such problems occur, you can amend the check-in to hide the
779ddef… wyoung 232 incorrect name from Fossil reports, but the original values remain in
779ddef… wyoung 233 the repository [forever][shun]. It is [difficult enough][fos] to fix
779ddef… wyoung 234 such problems automatically during sync that we are unlikely to ever do
779ddef… wyoung 235 so.
779ddef… wyoung 236
779ddef… wyoung 237 [auo]: /help?name=new
779ddef… wyoung 238 [fos]: ./impl.md#filter
779ddef… wyoung 239 [shun]: ../shunning.wiki
779ddef… wyoung 240
779ddef… wyoung 241
779ddef… wyoung 242
93cee1f… wyoung 243 ## <a id="utclone"></a>Cloning the User Table
779ddef… wyoung 244
779ddef… wyoung 245 When cloning over HTTP, the initial user table in the local clone is set
779ddef… wyoung 246 to its “[new state:](#new)” only one user with Setup capability, named
779ddef… wyoung 247 after either your OS user account, per the default above, or after the
779ddef… wyoung 248 user given in the clone URL.
779ddef… wyoung 249
779ddef… wyoung 250 There is one exception: if you clone as a named Setup user, you get a
779ddef… wyoung 251 complete copy of the user information. This restriction keeps the user
779ddef… wyoung 252 table private except for the only user allowed to make absolutely
779ddef… wyoung 253 complete clones of a remote repo, such as for failover or backup
779ddef… wyoung 254 purposes. Every other user’s clone is missing this and a few other
779ddef… wyoung 255 items, either for information security or PII privacy reasons.
779ddef… wyoung 256
779ddef… wyoung 257 When cloning with file system paths, `file://` URLs, or over SSH, you
779ddef… wyoung 258 get a complete clone, including the parent repo’s complete user table.
779ddef… wyoung 259
779ddef… wyoung 260 All of the above applies to [login groups][lg] as well.
779ddef… wyoung 261
779ddef… wyoung 262
93cee1f… wyoung 263 ## <a id="webonly"></a>Caps Affect Web Interfaces Only
50eeced… wyoung 264
50eeced… wyoung 265 Fossil’s user capability system only affects accesses over `http[s]://`
50eeced… wyoung 266 URLs. This includes clone, sync/push/pull, the [UI pages][wp], and [the
50eeced… wyoung 267 JSON API][japi]. For everything else, the user caps aren’t consulted at
50eeced… wyoung 268 all.
50eeced… wyoung 269
50eeced… wyoung 270 The only checks made when working directly with a local repository are
50eeced… wyoung 271 the operating system’s file system permissions. This should strike you
391bc36… wyoung 272 as sensible, since if you have read access to the repository file, you
391bc36… wyoung 273 can do anything you want to that repo DB including giving your user’s
391bc36… wyoung 274 record the [**Setup**][s] capability, after which Fossil’s user
391bc36… wyoung 275 capability system is effectively bypassed. (Or, create another Setup
391bc36… wyoung 276 user, with the same end effect.) If you’re objecting that you need
391bc36… wyoung 277 *write* access to the DB file to achieve this, realize that you can copy
391bc36… wyoung 278 a read-only file to another location, giving yourself write access to
391bc36… wyoung 279 it.
391bc36… wyoung 280
391bc36… wyoung 281 This is why the `fossil ui` command
50eeced… wyoung 282 gives you Setup permissions within Fossil UI: it can’t usefully prevent
50eeced… wyoung 283 you from doing anything through the UI since only the local file system
391bc36… wyoung 284 permissions actually matter, and you can’t start `fossil ui` without
391bc36… wyoung 285 having at least read access to that file.
50eeced… wyoung 286
50eeced… wyoung 287 What may be more surprising to you is that this is also true when
50eeced… wyoung 288 working on a *clone* done over a local file path, except that there are
50eeced… wyoung 289 then two sets of file system permission checks: once to modify the
50eeced… wyoung 290 working check-out’s repo clone DB file, then again on [sync][sync] with
50eeced… wyoung 291 the parent DB file. The Fossil capability checks are effectively
50eeced… wyoung 292 defeated because your user has [**Setup**][s] capability on both sides
50eeced… wyoung 293 of the sync. Be aware that those file checks do still matter, however:
50eeced… wyoung 294 Fossil requires write access to a repo DB while cloning from it, so you
50eeced… wyoung 295 can’t clone from a read-only repo DB file over a local file path.
50eeced… wyoung 296
be8ed97… wyoung 297 Even more surprising to you may be the fact that user caps do not affect
be8ed97… wyoung 298 cloning and syncing over SSH! (Not unless you go [out of your way][sshfc]
a3be0b8… drh 299 to patch around it, at any rate.) When you make a change to such a
be8ed97… wyoung 300 repository, the stock Fossil behavior is that the change first goes to the
be8ed97… wyoung 301 local repo clone where file system
50eeced… wyoung 302 permissions are all that matter, but then upon sync, the situation is
50eeced… wyoung 303 effectively the same as when the parent repo is on the local file
50eeced… wyoung 304 system. The reason behind this is that if you can log into the remote
50eeced… wyoung 305 system over SSH and that user has the necessary file system permissions
50eeced… wyoung 306 on that remote repo DB file to allow clone and sync operations, then
50eeced… wyoung 307 we’re back in the same situation as with local files: there’s no point
50eeced… wyoung 308 trying to enforce the Fossil user capabilities when you can just modify
be8ed97… wyoung 309 the remote DB directly, so the operation proceeds unimpeded by any user
be8ed97… wyoung 310 capability settings on the remote repo.
50eeced… wyoung 311
50eeced… wyoung 312 Where this gets confusing is that *all* Fossil syncs are done over the
50eeced… wyoung 313 HTTP protocol, including those done over `file://` and `ssh://` URLs,
50eeced… wyoung 314 not just those done over `http[s]://` URLs:
779ddef… wyoung 315
779ddef… wyoung 316 * For `ssh://` URLs, Fossil pipes the HTTP conversation through a
779ddef… wyoung 317 local SSH client to a remote instance of Fossil running the
50eeced… wyoung 318 [`test-http`](/help?name=test-http) command to receive the tunneled
be8ed97… wyoung 319 HTTP connection. [This interface is intentionally permissionless][sxycap].
779ddef… wyoung 320
50eeced… wyoung 321 * For `file://` URLs — as opposed to plain local file paths —
50eeced… wyoung 322 the “sending” Fossil instance writes its side of
779ddef… wyoung 323 the HTTP conversation out to a temporary file in the same directory
779ddef… wyoung 324 as the local repo clone and then calls itself on the “receiving”
779ddef… wyoung 325 repository to read that same HTTP transcript file back in to apply
50eeced… wyoung 326 those changes to that repository. Presumably Fossil does this
50eeced… wyoung 327 instead of using a pipe to ease portability to Windows.
50eeced… wyoung 328
be8ed97… wyoung 329 Despite use of HTTP for these URL types, the fact remains that
be8ed97… wyoung 330 checks for capabilities like [**Read**][o] and [**Write**][i] within the
50eeced… wyoung 331 HTTP conversation between two Fossil instances only have a useful effect
50eeced… wyoung 332 when done over an `http[s]://` URL.
50eeced… wyoung 333
be8ed97… wyoung 334 [sshfc]: ../server/any/http-over-ssh.md
34de621… wyoung 335 [sxycap]: /file?ci=ec5efceb8aac6cb4&name=src/main.c&ln=2748-2752
779ddef… wyoung 336
779ddef… wyoung 337
93cee1f… wyoung 338 ## <a id="pubpg"></a>Public Pages
779ddef… wyoung 339
779ddef… wyoung 340 In Admin → Access, there is an option for giving a list of [globs][glob]
779ddef… wyoung 341 to name URLs which get treated as if the visitor had [the default cap
779ddef… wyoung 342 set](#defcap). For example, you could take the [**Read**][o] capability
779ddef… wyoung 343 away from the “nobody” user category, who has it by default, to prevent
779ddef… wyoung 344 users without logins from pulling down your repository contents one
779ddef… wyoung 345 artifact at a time, yet give those users the ability to read the project
779ddef… wyoung 346 documentation by setting the glob to match your [embedded
779ddef… wyoung 347 documentation][edoc]’s URL root.
779ddef… wyoung 348
779ddef… wyoung 349
93cee1f… wyoung 350 ## <a id="defcap"></a>Default User Capability Set
779ddef… wyoung 351
779ddef… wyoung 352 In Admin → Access, you can define a default user capability set, which
779ddef… wyoung 353 is used as:
779ddef… wyoung 354
779ddef… wyoung 355 1. the default caps for users newly created by an Admin or Setup user
779ddef… wyoung 356 2. the default caps for self-registered users, an option in that same UI
779ddef… wyoung 357 3. the effective caps for URIs considered [public pages](#pubpg)
779ddef… wyoung 358
779ddef… wyoung 359 This defaults to [**Reader**][u].
779ddef… wyoung 360
779ddef… wyoung 361
779ddef… wyoung 362 <!-- add padding so anchor links always scroll ref’d section to top -->
779ddef… wyoung 363 <div style="height: 75em"></div>
779ddef… wyoung 364
779ddef… wyoung 365 [ref]: ./ref.html
779ddef… wyoung 366
779ddef… wyoung 367 [a]: ./ref.html#a
779ddef… wyoung 368 [b]: ./ref.html#b
779ddef… wyoung 369 [c]: ./ref.html#c
779ddef… wyoung 370 [d]: ./ref.html#d
779ddef… wyoung 371 [e]: ./ref.html#e
779ddef… wyoung 372 [f]: ./ref.html#f
779ddef… wyoung 373 [g]: ./ref.html#g
779ddef… wyoung 374 [h]: ./ref.html#h
779ddef… wyoung 375 [i]: ./ref.html#i
779ddef… wyoung 376 [j]: ./ref.html#j
779ddef… wyoung 377 [k]: ./ref.html#k
779ddef… wyoung 378 [l]: ./ref.html#l
779ddef… wyoung 379 [m]: ./ref.html#m
779ddef… wyoung 380 [n]: ./ref.html#n
779ddef… wyoung 381 [o]: ./ref.html#o
779ddef… wyoung 382 [p]: ./ref.html#p
779ddef… wyoung 383 [q]: ./ref.html#q
779ddef… wyoung 384 [r]: ./ref.html#r
779ddef… wyoung 385 [s]: ./ref.html#s
779ddef… wyoung 386 [t]: ./ref.html#t
779ddef… wyoung 387 [u]: ./ref.html#u
779ddef… wyoung 388 [v]: ./ref.html#v
779ddef… wyoung 389 [w]: ./ref.html#w
779ddef… wyoung 390 [x]: ./ref.html#x
779ddef… wyoung 391 [y]: ./ref.html#y
779ddef… wyoung 392 [z]: ./ref.html#z
779ddef… wyoung 393
779ddef… wyoung 394 [2]: ./ref.html#2
779ddef… wyoung 395 [3]: ./ref.html#3
779ddef… wyoung 396 [4]: ./ref.html#4
779ddef… wyoung 397 [5]: ./ref.html#5
779ddef… wyoung 398 [6]: ./ref.html#6
779ddef… wyoung 399 [7]: ./ref.html#7
779ddef… wyoung 400
779ddef… wyoung 401 [glob]: https://en.wikipedia.org/wiki/Glob_(programming)
779ddef… wyoung 402 [japi]: https://docs.google.com/document/d/1fXViveNhDbiXgCuE7QDXQOKeFzf2qNUkBEgiUvoqFN4/view#heading=h.6k0k5plm18p1
779ddef… wyoung 403 [sp]: ../sync.wiki
779ddef… wyoung 404 [sync]: /help?name=sync
779ddef… wyoung 405 [wp]: /help#webpages

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button