]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blobdiff - docs/frontends/webapi.rst
webapi.rst: document Range: header on GET requests
[tahoe-lafs/tahoe-lafs.git] / docs / frontends / webapi.rst
index eeeb1da6d7b1a7e8575358b5c7da92c3c45f84f5..c3dcea6c7e12f0e73662dd03c72cfcd4a29bf874 100644 (file)
@@ -1,3 +1,5 @@
+.. -*- coding: utf-8-with-signature -*-
+
 ==========================
 The Tahoe REST-ful Web API
 ==========================
@@ -6,7 +8,7 @@ The Tahoe REST-ful Web API
 2.  `Basic Concepts: GET, PUT, DELETE, POST`_
 3.  `URLs`_
 
-       1. `Child Lookup`_
+    1. `Child Lookup`_
 
 4.  `Slow Operations, Progress, and Cancelling`_
 5.  `Programmatic Operations`_
@@ -14,28 +16,31 @@ The Tahoe REST-ful Web API
     1. `Reading a file`_
     2. `Writing/Uploading a File`_
     3. `Creating a New Directory`_
-    4. `Get Information About A File Or Directory (as JSON)`_
-    5. `Attaching an existing File or Directory by its read- or write-cap`_
-    6. `Adding multiple files or directories to a parent directory at once`_
-    7. `Deleting a File or Directory`_
+    4. `Getting Information About a File Or Directory (as JSON)`_
+    5. `Attaching an Existing File or Directory by its read- or write-cap`_
+    6. `Adding Multiple Files or Directories to a Parent Directory at Once`_
+    7. `Unlinking a File or Directory`_
 
 6.  `Browser Operations: Human-Oriented Interfaces`_
 
-    1.  `Viewing A Directory (as HTML)`_
+    1.  `Viewing a Directory (as HTML)`_
     2.  `Viewing/Downloading a File`_
-    3.  `Get Information About A File Or Directory (as HTML)`_
+    3.  `Getting Information About a File Or Directory (as HTML)`_
     4.  `Creating a Directory`_
     5.  `Uploading a File`_
-    6.  `Attaching An Existing File Or Directory (by URI)`_
-    7.  `Deleting A Child`_
-    8.  `Renaming A Child`_
-    9.  `Other Utilities`_
-    10. `Debugging and Testing Features`_
+    6.  `Attaching an Existing File Or Directory (by URI)`_
+    7.  `Unlinking a Child`_
+    8.  `Renaming a Child`_
+    9.  `Relinking ("Moving") a Child`_
+    10. `Other Utilities`_
+    11. `Debugging and Testing Features`_
 
 7.  `Other Useful Pages`_
 8.  `Static Files in /public_html`_
-9.  `Safety and security issues -- names vs. URIs`_
+9.  `Safety and Security Issues -- Names vs. URIs`_
 10. `Concurrency Issues`_
+11. `Access Blacklist`_
+
 
 Enabling the web-API port
 =========================
@@ -49,8 +54,7 @@ section of $NODEDIR/tahoe.cfg will cause the node to run a webserver on port
 This string is actually a Twisted "strports" specification, meaning you can
 get more control over the interface to which the server binds by supplying
 additional arguments. For more details, see the documentation on
-`twisted.application.strports
-<http://twistedmatrix.com/documents/current/api/twisted.application.strports.html>`_.
+`twisted.application.strports`_.
 
 Writing "tcp:3456:interface=127.0.0.1" into the web.port line does the same
 but binds to the loopback interface, ensuring that only the programs on the
@@ -61,17 +65,19 @@ This webport can be set when the node is created by passing a --webport
 option to the 'tahoe create-node' command. By default, the node listens on
 port 3456, on the loopback (127.0.0.1) interface.
 
+.. _twisted.application.strports: https://twistedmatrix.com/documents/current/api/twisted.application.strports.html
+
+
 Basic Concepts: GET, PUT, DELETE, POST
 ======================================
 
-As described in `docs/architecture.rst <../architecture.rst>`_, each file
-and directory in a Tahoe virtual filesystem is referenced by an identifier
-that combines the designation of the object with the authority to do something
-with it (such as read or modify the contents). This identifier is called a
-"read-cap" or "write-cap", depending upon whether it enables read-only or
-read-write access. These "caps" are also referred to as URIs (which may be
-confusing because they are not currently `RFC3986
-<http://tools.ietf.org/html/rfc3986>`_-compliant URIs).
+As described in `docs/architecture.rst`_, each file and directory in a Tahoe
+virtual filesystem is referenced by an identifier that combines the
+designation of the object with the authority to do something with it (such as
+read or modify the contents). This identifier is called a "read-cap" or
+"write-cap", depending upon whether it enables read-only or read-write
+access. These "caps" are also referred to as URIs (which may be confusing
+because they are not currently RFC3986_-compliant URIs).
 
 The Tahoe web-based API is "REST-ful", meaning it implements the concepts of
 "REpresentational State Transfer": the original scheme by which the World
@@ -88,15 +94,16 @@ URL) will return information about the object, such as metadata. GET
 operations are required to have no side-effects.
 
 PUT is used to upload new objects into the filesystem, or to replace an
-existing object. DELETE it used to delete objects from the filesystem. Both
-PUT and DELETE are required to be idempotent: performing the same operation
-multiple times must have the same side-effects as only performing it once.
+existing link or the contents of a mutable file. DELETE is used to unlink
+objects from directories. Both PUT and DELETE are required to be idempotent:
+performing the same operation multiple times must have the same side-effects
+as only performing it once.
 
 POST is used for more complicated actions that cannot be expressed as a GET,
 PUT, or DELETE. POST operations can be thought of as a method call: sending
 some message to the object referenced by the URL. In Tahoe, POST is also used
 for operations that must be triggered by an HTML form (including upload and
-delete), because otherwise a regular web browser has no way to accomplish
+unlinking), because otherwise a regular web browser has no way to accomplish
 these tasks. In general, everything that can be done with a PUT or DELETE can
 also be done with a POST.
 
@@ -105,11 +112,11 @@ a program that needs to manipulate the virtual file system. Such programs are
 expected to use the RESTful interface described above. The second is a human
 using a standard web browser to work with the filesystem. This user is given
 a series of HTML pages with links to download files, and forms that use POST
-actions to upload, rename, and delete files.
+actions to upload, rename, and unlink files.
 
 When an error occurs, the HTTP response code will be set to an appropriate
 400-series code (like 404 Not Found for an unknown childname, or 400 Bad Request
-when the parameters to a webapi operation are invalid), and the HTTP response
+when the parameters to a web-API operation are invalid), and the HTTP response
 body will usually contain a few lines of explanation as to the cause of the
 error and possible responses. Unusual exceptions may result in a 500 Internal
 Server Error as a catch-all, with a default response body containing
@@ -120,6 +127,10 @@ a plain text stack trace instead. If the Accept header contains ``*/*``, or
 ``text/*``, or text/html (or if there is no Accept header), HTML tracebacks will
 be generated.
 
+.. _RFC3986: https://tools.ietf.org/html/rfc3986
+.. _docs/architecture.rst: ../architecture.rst
+
+
 URLs
 ====
 
@@ -151,9 +162,7 @@ listening on this port::
 
  http://127.0.0.1:3456/uri/ + $CAP
 
-So, to access the directory named above (which happens to be the
-publically-writeable sample directory on the Tahoe test grid, described at
-http://allmydata.org/trac/tahoe/wiki/TestGrid), the URL would be::
+So, to access the directory named above, the URL would be::
 
  http://127.0.0.1:3456/uri/URI%3ADIR2%3Adjrdkfawoqihigoett4g6auz6a%3Ajx5mplfpwexnoqff7y5e4zjus4lidm76dcuarpct7cckorh2dpgq/
 
@@ -178,6 +187,8 @@ server prefix. They will be displayed like this::
  /uri/$DIRCAP/
  /uri/$FILECAP
 
+/cap can be used as a synonym for /uri.  If interoperability with older web-API
+servers is required, /uri should be used.
 
 Child Lookup
 ------------
@@ -226,16 +237,17 @@ with::
 Also note that the filenames inside upload POST forms are interpreted using
 whatever character set was provided in the conventional '_charset' field, and
 defaults to UTF-8 if not otherwise specified. The JSON representation of each
-directory contains native unicode strings. Tahoe directories are specified to
-contain unicode filenames, and cannot contain binary strings that are not
+directory contains native Unicode strings. Tahoe directories are specified to
+contain Unicode filenames, and cannot contain binary strings that are not
 representable as such.
 
 All Tahoe operations that refer to existing files or directories must include
-a suitable read- or write- cap in the URL: the webapi server won't add one
+a suitable read- or write- cap in the URL: the web-API server won't add one
 for you. If you don't know the cap, you can't access the file. This allows
-the security properties of Tahoe caps to be extended across the webapi
+the security properties of Tahoe caps to be extended across the web-API
 interface.
 
+
 Slow Operations, Progress, and Cancelling
 =========================================
 
@@ -316,6 +328,7 @@ operations have streaming equivalents. These equivalents do not use operation
 handles. Instead, they emit line-oriented status results immediately. Client
 code can cancel the operation by simply closing the HTTP connection.
 
+
 Programmatic Operations
 =======================
 
@@ -326,7 +339,8 @@ can be performed on these URLs. This set of operations are aimed at programs
 that use HTTP to communicate with a Tahoe node. A later section describes
 operations that are intended for web browsers.
 
-Reading A File
+
+Reading a File
 --------------
 
 ``GET /uri/$FILECAP``
@@ -334,14 +348,18 @@ Reading A File
 ``GET /uri/$DIRCAP/[SUBDIRS../]FILENAME``
 
  This will retrieve the contents of the given file. The HTTP response body
- will contain the sequence of bytes that make up the file.
+ will contain the sequence of bytes that make up the file. The "Range:"
+ header can be used to restrict which portions of the file are returned (see
+ RFC 2616 section 14.35.1 "Byte Ranges"), however Tahoe only supports a
+ single "bytes" range and never provides a `multipart/byteranges` response.
 
  To view files in a web browser, you may want more control over the
  Content-Type and Content-Disposition headers. Please see the next section
  "Browser Operations", for details on how to modify these URLs for that
  purpose.
 
-Writing/Uploading A File
+
+Writing/Uploading a File
 ------------------------
 
 ``PUT /uri/$FILECAP``
@@ -357,13 +375,34 @@ Writing/Uploading A File
  To use the /uri/$FILECAP form, $FILECAP must be a write-cap for a mutable file.
 
  In the /uri/$DIRCAP/[SUBDIRS../]FILENAME form, if the target file is a
- writeable mutable file, that file's contents will be overwritten in-place. If
- it is a read-cap for a mutable file, an error will occur. If it is an
- immutable file, the old file will be discarded, and a new one will be put in
- its place.
-
- When creating a new file, if "mutable=true" is in the query arguments, the
- operation will create a mutable file instead of an immutable one.
+ writeable mutable file, that file's contents will be overwritten
+ in-place. If it is a read-cap for a mutable file, an error will occur.
+ If it is an immutable file, the old file will be discarded, and a new
+ one will be put in its place. If the target file is a writable mutable
+ file, you may also specify an "offset" parameter -- a byte offset that
+ determines where in the mutable file the data from the HTTP request
+ body is placed. This operation is relatively efficient for MDMF mutable
+ files, and is relatively inefficient (but still supported) for SDMF
+ mutable files. If no offset parameter is specified, then the entire
+ file is replaced with the data from the HTTP request body. For an
+ immutable file, the "offset" parameter is not valid.
+
+ When creating a new file, you can control the type of file created by
+ specifying a format= argument in the query string. format=MDMF creates an
+ MDMF mutable file. format=SDMF creates an SDMF mutable file. format=CHK
+ creates an immutable file. The value of the format argument is
+ case-insensitive. If no format is specified, the newly-created file will be
+ immutable (but see below).
+
+ For compatibility with previous versions of Tahoe-LAFS, the web-API will
+ also accept a mutable=true argument in the query string. If mutable=true is
+ given, then the new file will be mutable, and its format will be the default
+ mutable file format, as configured by the [client]mutable.format option of
+ tahoe.cfg on the Tahoe-LAFS node hosting the webapi server. Use of
+ mutable=true is discouraged; new code should use format= instead of
+ mutable=true (unless it needs to be compatible with web-API servers older
+ than v1.9.0). If neither format= nor mutable=true are given, the
+ newly-created file will be immutable.
 
  This returns the file-cap of the resulting file. If a new file was created
  by this method, the HTTP response code (as dictated by rfc2616) will be set
@@ -379,11 +418,11 @@ Writing/Uploading A File
  attach the file into the filesystem. No directories will be modified by
  this operation. The file-cap is returned as the body of the HTTP response.
 
- If "mutable=true" is in the query arguments, the operation will create a
- mutable file, and return its write-cap in the HTTP respose. The default is
to create an immutable file, returning the read-cap as a response.
+ This method accepts format= and mutable=true as query string arguments, and
+ interprets those arguments in the same way as the linked forms of PUT
described immediately above.
 
-Creating A New Directory
+Creating a New Directory
 ------------------------
 
 ``POST /uri?t=mkdir``
@@ -395,12 +434,23 @@ Creating A New Directory
  filesystem. The "PUT" operation is provided for backwards compatibility:
  new code should use POST.
 
+ This supports a format= argument in the query string. The format=
+ argument, if specified, controls the format of the directory. format=MDMF
+ indicates that the directory should be stored as an MDMF file; format=SDMF
+ indicates that the directory should be stored as an SDMF file. The value of
+ the format= argument is case-insensitive. If no format= argument is
+ given, the directory's format is determined by the default mutable file
+ format, as configured on the Tahoe-LAFS node responding to the request.
+
 ``POST /uri?t=mkdir-with-children``
 
  Create a new directory, populated with a set of child nodes, and return its
  write-cap as the HTTP response body. The new directory is not attached to
  any other directory: the returned write-cap is the only reference to it.
 
+ The format of the directory can be controlled with the format= argument in
+ the query string, as described above.
+
  Initial children are provided as the body of the POST form (this is more
  efficient than doing separate mkdir and set_children operations). If the
  body is empty, the new directory will be empty. If not empty, the body will
@@ -415,7 +465,6 @@ Creating A New Directory
   {
     "Fran\u00e7ais": [ "filenode", {
         "ro_uri": "URI:CHK:...",
-        "size": bytes,
         "metadata": {
           "ctime": 1202777696.7564139,
           "mtime": 1202777696.7564139,
@@ -436,40 +485,38 @@ Creating A New Directory
   }
 
  For forward-compatibility, a mutable directory can also contain caps in
- a format that is unknown to the webapi server. When such caps are retrieved
+ a format that is unknown to the web-API server. When such caps are retrieved
  from a mutable directory in a "ro_uri" field, they will be prefixed with
  the string "ro.", indicating that they must not be decoded without
  checking that they are read-only. The "ro." prefix must not be stripped
- off without performing this check. (Future versions of the webapi server
+ off without performing this check. (Future versions of the web-API server
  will perform it where necessary.)
 
  If both the "rw_uri" and "ro_uri" fields are present in a given PROPDICT,
- and the webapi server recognizes the rw_uri as a write cap, then it will
+ and the web-API server recognizes the rw_uri as a write cap, then it will
  reset the ro_uri to the corresponding read cap and discard the original
  contents of ro_uri (in order to ensure that the two caps correspond to the
  same object and that the ro_uri is in fact read-only). However this may not
- happen for caps in a format unknown to the webapi server. Therefore, when
- writing a directory the webapi client should ensure that the contents
+ happen for caps in a format unknown to the web-API server. Therefore, when
+ writing a directory the web-API client should ensure that the contents
  of "rw_uri" and "ro_uri" for a given PROPDICT are a consistent
- (write cap, read cap) pair if possible. If the webapi client only has
+ (write cap, read cap) pair if possible. If the web-API client only has
  one cap and does not know whether it is a write cap or read cap, then
  it is acceptable to set "rw_uri" to that cap and omit "ro_uri". The
  client must not put a write cap into a "ro_uri" field.
 
  The metadata may have a "no-write" field. If this is set to true in the
  metadata of a link, it will not be possible to open that link for writing
- via the SFTP frontend; see `FTP-and-SFTP.rst`_ for details.
- Also, if the "no-write" field is set to true in the metadata of a link to
- a mutable child, it will cause the link to be diminished to read-only.
- .. _FTP-and-SFTP.rst: http://tahoe-lafs.org/source/tahoe-lafs/trunk/docs/frontents/FTP-and-SFTP.rst
+ via the SFTP frontend; see FTP-and-SFTP.rst_ for details.  Also, if the
+ "no-write" field is set to true in the metadata of a link to a mutable
+ child, it will cause the link to be diminished to read-only.
 
- Note that the webapi-using client application must not provide the
+ Note that the web-API-using client application must not provide the
  "Content-Type: multipart/form-data" header that usually accompanies HTML
  form submissions, since the body is not formatted this way. Doing so will
  cause a server error as the lower-level code misparses the request body.
 
- Child file names should each be expressed as a unicode string, then used as
+ Child file names should each be expressed as a Unicode string, then used as
  keys of the dictionary. The dictionary should then be converted into JSON,
  and the resulting string encoded into UTF-8. This UTF-8 bytestring should
  then be used as the POST body.
@@ -482,18 +529,18 @@ Creating A New Directory
  immutable files, literal files, and deep-immutable directories.
 
  For forward-compatibility, a deep-immutable directory can also contain caps
- in a format that is unknown to the webapi server. When such caps are retrieved
+ in a format that is unknown to the web-API server. When such caps are retrieved
  from a deep-immutable directory in a "ro_uri" field, they will be prefixed
  with the string "imm.", indicating that they must not be decoded without
  checking that they are immutable. The "imm." prefix must not be stripped
- off without performing this check. (Future versions of the webapi server
+ off without performing this check. (Future versions of the web-API server
  will perform it where necessary.)
  
  The cap for each child may be given either in the "rw_uri" or "ro_uri"
  field of the PROPDICT (not both). If a cap is given in the "rw_uri" field,
- then the webapi server will check that it is an immutable read-cap of a
+ then the web-API server will check that it is an immutable read-cap of a
  *known* format, and give an error if it is not. If a cap is given in the
- "ro_uri" field, then the webapi server will still check whether known
+ "ro_uri" field, then the web-API server will still check whether known
  caps are immutable, but for unknown caps it will simply assume that the
  cap can be stored, as described above. Note that an attacker would be
  able to store any cap in an immutable directory, so this check when
@@ -514,6 +561,14 @@ Creating A New Directory
 
  If the final directory is created, it will be empty.
 
+ This accepts a format= argument in the query string, which controls the
+ format of the named target directory, if it does not already exist. format=
+ is interpreted in the same way as in the POST /uri?t=mkdir form. Note that
+ format= only controls the format of the named target directory;
+ intermediate directories, if created, are created based on the default
+ mutable type, as configured on the Tahoe-LAFS server responding to the
+ request.
+
  This operation will return an error if a blocking file is present at any of
  the parent names, preventing the server from creating the necessary parent
  directory; or if it would require changing an immutable directory.
@@ -528,6 +583,14 @@ Creating A New Directory
  intermediate mutable directories as necessary. If the final directory is
  created, it will be populated with initial children from the POST request
  body, as described above.
+
+ This accepts a format= argument in the query string, which controls the
+ format of the target directory, if the target directory is created as part
+ of the operation. format= is interpreted in the same way as in the POST/
+ uri?t=mkdir-with-children operation. Note that format= only controls the
+ format of the named target directory; intermediate directories, if created,
+ are created using the default mutable type setting, as configured on the
+ Tahoe-LAFS server responding to the request.
  
  This operation will return an error if a blocking file is present at any of
  the parent names, preventing the server from creating the necessary parent
@@ -552,6 +615,14 @@ Creating A New Directory
  Create a new empty mutable directory and attach it to the given existing
  directory. This will create additional intermediate directories as necessary.
 
+ This accepts a format= argument in the query string, which controls the
+ format of the named target directory, if it does not already exist. format=
+ is interpreted in the same way as in the POST /uri?t=mkdir form. Note that
+ format= only controls the format of the named target directory;
+ intermediate directories, if created, are created based on the default
+ mutable type, as configured on the Tahoe-LAFS server responding to the
+ request.
+
  This operation will return an error if a blocking file is present at any of
  the parent names, preventing the server from creating the necessary parent
  directory, or if it would require changing any immutable directory.
@@ -565,7 +636,15 @@ Creating A New Directory
  Like /uri/$DIRCAP/[SUBDIRS../]?t=mkdir&name=NAME, but the new directory will
  be populated with initial children via the POST request body. This command
  will create additional intermediate mutable directories as necessary.
+
+ This accepts a format= argument in the query string, which controls the
+ format of the target directory, if the target directory is created as part
+ of the operation. format= is interpreted in the same way as in the POST/
+ uri?t=mkdir-with-children operation. Note that format= only controls the
+ format of the named target directory; intermediate directories, if created,
+ are created using the default mutable type setting, as configured on the
+ Tahoe-LAFS server responding to the request.
+
  This operation will return an error if a blocking file is present at any of
  the parent names, preventing the server from creating the necessary parent
  directory; or if it would require changing an immutable directory; or if
@@ -587,8 +666,11 @@ Creating A New Directory
  This operation will return an error if the parent directory is immutable,
  or already has a child named NAME.
 
-Get Information About A File Or Directory (as JSON)
----------------------------------------------------
+.. _FTP-and-SFTP.rst: FTP-and-SFTP.rst
+
+
+Getting Information About a File Or Directory (as JSON)
+-------------------------------------------------------
 
 ``GET /uri/$FILECAP?t=json``
 
@@ -607,11 +689,12 @@ Get Information About A File Or Directory (as JSON)
   GET /uri/$FILECAP?t=json :
 
    [ "filenode", {
-        "ro_uri": file_uri,
-        "verify_uri": verify_uri,
-        "size": bytes,
-        "mutable": false
-        } ]
+      "ro_uri": file_uri,
+      "verify_uri": verify_uri,
+      "size": bytes,
+      "mutable": false,
+      "format": "CHK"
+     } ]
 
  If it is a capability to a directory followed by a path from that directory
  to a file, then the information also includes metadata from the link to the
@@ -620,17 +703,18 @@ Get Information About A File Or Directory (as JSON)
   GET /uri/$DIRCAP/[SUBDIRS../]FILENAME?t=json
 
    [ "filenode", {
-        "ro_uri": file_uri,
-        "verify_uri": verify_uri,
-        "size": bytes,
-        "mutable": false,
-        "metadata": {
-          "ctime": 1202777696.7564139,
-          "mtime": 1202777696.7564139,
-          "tahoe": {
-                "linkcrtime": 1202777696.7564139,
-                "linkmotime": 1202777696.7564139
-                } } } ]
+      "ro_uri": file_uri,
+      "verify_uri": verify_uri,
+      "size": bytes,
+      "mutable": false,
+      "format": "CHK",
+      "metadata": {
+       "ctime": 1202777696.7564139,
+       "mtime": 1202777696.7564139,
+       "tahoe": {
+        "linkcrtime": 1202777696.7564139,
+        "linkmotime": 1202777696.7564139
+       } } } ]
 
  If it is a directory, then it includes information about the children of
  this directory, as a mapping from child name to a set of data about the
@@ -643,32 +727,35 @@ Get Information About A File Or Directory (as JSON)
   GET /uri/$DIRCAP/[SUBDIRS../]SUBDIR?t=json :
 
    [ "dirnode", {
-        "rw_uri": read_write_uri,
-        "ro_uri": read_only_uri,
-        "verify_uri": verify_uri,
-        "mutable": true,
-        "children": {
-          "foo.txt": [ "filenode", {
-                  "ro_uri": uri,
-                  "size": bytes,
-                  "metadata": {
-                        "ctime": 1202777696.7564139,
-                        "mtime": 1202777696.7564139,
-                        "tahoe": {
-                          "linkcrtime": 1202777696.7564139,
-                          "linkmotime": 1202777696.7564139
-                          } } } ],
-          "subdir":  [ "dirnode", {
-                  "rw_uri": rwuri,
-                  "ro_uri": rouri,
-                  "metadata": {
-                        "ctime": 1202778102.7589991,
-                        "mtime": 1202778111.2160511,
-                        "tahoe": {
-                          "linkcrtime": 1202777696.7564139,
-                          "linkmotime": 1202777696.7564139
-                        } } } ]
-        } } ]
+     "rw_uri": read_write_uri,
+     "ro_uri": read_only_uri,
+     "verify_uri": verify_uri,
+     "mutable": true,
+     "format": "SDMF",
+     "children": {
+      "foo.txt": [ "filenode",
+                   {
+                     "ro_uri": uri,
+                     "size": bytes,
+                     "metadata": {
+                       "ctime": 1202777696.7564139,
+                       "mtime": 1202777696.7564139,
+                       "tahoe": {
+                         "linkcrtime": 1202777696.7564139,
+                         "linkmotime": 1202777696.7564139
+                       } } } ],
+      "subdir":  [ "dirnode",
+                   {
+                     "rw_uri": rwuri,
+                     "ro_uri": rouri,
+                     "metadata": {
+                       "ctime": 1202778102.7589991,
+                       "mtime": 1202778111.2160511,
+                       "tahoe": {
+                         "linkcrtime": 1202777696.7564139,
+                         "linkmotime": 1202777696.7564139
+                       } } } ]
+      } } ]
 
  In the above example, note how 'children' is a dictionary in which the keys
  are child names and the values depend upon whether the child is a file or a
@@ -688,22 +775,22 @@ Get Information About A File Or Directory (as JSON)
   GET /uri/$UNKNOWNCAP?t=json :
 
    [ "unknown", {
-        "ro_uri": unknown_read_uri
-        } ]
+       "ro_uri": unknown_read_uri
+       } ]
 
   GET /uri/$DIRCAP/[SUBDIRS../]UNKNOWNCHILDNAME?t=json :
 
    [ "unknown", {
-        "rw_uri": unknown_write_uri,
-        "ro_uri": unknown_read_uri,
-        "mutable": true,
-        "metadata": {
-          "ctime": 1202777696.7564139,
-          "mtime": 1202777696.7564139,
-          "tahoe": {
-                "linkcrtime": 1202777696.7564139,
-                "linkmotime": 1202777696.7564139
-                } } } ]
+       "rw_uri": unknown_write_uri,
+       "ro_uri": unknown_read_uri,
+       "mutable": true,
+       "metadata": {
+         "ctime": 1202777696.7564139,
+         "mtime": 1202777696.7564139,
+         "tahoe": {
+           "linkcrtime": 1202777696.7564139,
+           "linkmotime": 1202777696.7564139
+         } } } ]
 
  As in the case of file nodes, the metadata will only be present when the
  capability is to a directory followed by a path. The "mutable" field is also
@@ -731,7 +818,7 @@ In Tahoe earlier than v1.4.0, 'mtime' and 'ctime' keys were populated
 instead of the 'tahoe':'linkmotime' and 'tahoe':'linkcrtime' keys. Starting
 in Tahoe v1.4.0, the 'linkmotime'/'linkcrtime' keys in the 'tahoe' sub-dict
 are populated. However, prior to Tahoe v1.7beta, a bug caused the 'tahoe'
-sub-dict to be deleted by webapi requests in which new metadata is
+sub-dict to be deleted by web-API requests in which new metadata is
 specified, and not to be added to existing child links that lack it.
 
 From Tahoe v1.7.0 onward, the 'mtime' and 'ctime' fields are no longer
@@ -800,7 +887,7 @@ There are several ways that the 'ctime' field could be confusing:
    time.
 
 
-Attaching an existing File or Directory by its read- or write-cap
+Attaching an Existing File or Directory by its read- or write-cap
 -----------------------------------------------------------------
 
 ``PUT /uri/$DIRCAP/[SUBDIRS../]CHILDNAME?t=uri``
@@ -831,7 +918,7 @@ Attaching an existing File or Directory by its read- or write-cap
  
  Note that this operation does not take its child cap in the form of
  separate "rw_uri" and "ro_uri" fields. Therefore, it cannot accept a
- child cap in a format unknown to the webapi server, unless its URI
+ child cap in a format unknown to the web-API server, unless its URI
  starts with "ro." or "imm.". This restriction is necessary because the
  server is not able to attenuate an unknown write cap to a read cap.
  Unknown URIs starting with "ro." or "imm.", on the other hand, are
@@ -840,7 +927,8 @@ Attaching an existing File or Directory by its read- or write-cap
  would result in granting the cap's write authority to holders of the
  directory read cap.
 
-Adding multiple files or directories to a parent directory at once
+
+Adding Multiple Files or Directories to a Parent Directory at Once
 ------------------------------------------------------------------
 
 ``POST /uri/$DIRCAP/[SUBDIRS..]?t=set_children``
@@ -874,7 +962,7 @@ Adding multiple files or directories to a parent directory at once
  existing "tahoe" metadata is preserved. The metadata["tahoe"] value is
  reserved for metadata generated by the tahoe node itself. The only two keys
  currently placed here are "linkcrtime" and "linkmotime". For details, see
- the section above entitled "Get Information About A File Or Directory (as
+ the section above entitled "Getting Information About a File Or Directory (as
  JSON)", in the "About the metadata" subsection.
  
  Note that this command was introduced with the name "set_children", which
@@ -883,8 +971,8 @@ Adding multiple files or directories to a parent directory at once
  backward compatibility should continue to use "set_children".
 
 
-Deleting a File or Directory
-----------------------------
+Unlinking a File or Directory
+-----------------------------
 
 ``DELETE /uri/$DIRCAP/[SUBDIRS../]CHILDNAME``
 
@@ -893,7 +981,7 @@ Deleting a File or Directory
  be modified.
 
  Note that this does not actually delete the file or directory that the name
- points to from the tahoe grid -- it only removes the named reference from
+ points to from the tahoe grid -- it only unlinks the named reference from
  this directory. If there are other names in this directory or in other
  directories that point to the resource, then it will remain accessible
  through those paths. Even if all names pointing to this object are removed
@@ -912,6 +1000,7 @@ Deleting a File or Directory
  This method returns the file- or directory- cap of the object that was just
  removed.
 
+
 Browser Operations: Human-oriented interfaces
 =============================================
 
@@ -928,7 +1017,8 @@ separated from the main URL by "?", and from each other by "&". For example,
 specified by using <input type="hidden"> elements. For clarity, the
 descriptions below display the most significant arguments as URL query args.
 
-Viewing A Directory (as HTML)
+
+Viewing a Directory (as HTML)
 -----------------------------
 
 ``GET /uri/$DIRCAP/[SUBDIRS../]``
@@ -937,8 +1027,9 @@ Viewing A Directory (as HTML)
  browser, which contains HREF links to all files and directories reachable
  from this directory. These HREF links do not have a t= argument, meaning
  that a human who follows them will get pages also meant for a human. It also
- contains forms to upload new files, and to delete files and directories.
- Those forms use POST methods to do their job.
+ contains forms to upload new files, and to unlink files and directories
+ from their parent directory. Those forms use POST methods to do their job.
+
 
 Viewing/Downloading a File
 --------------------------
@@ -980,8 +1071,11 @@ Viewing/Downloading a File
  this form can *only* be used with file caps; it is an error to use a
  directory cap after the /named/ prefix.
 
-Get Information About A File Or Directory (as HTML)
----------------------------------------------------
+ URLs may also use /file/$FILECAP/FILENAME as a synonym for
+ /named/$FILECAP/FILENAME.
+
+Getting Information About a File Or Directory (as HTML)
+-------------------------------------------------------
 
 ``GET /uri/$FILECAP?t=info``
 
@@ -1001,7 +1095,8 @@ Get Information About A File Or Directory (as HTML)
  * access caps (URIs): verify-cap, read-cap, write-cap (for mutable objects)
  * check/verify/repair form
  * deep-check/deep-size/deep-stats/manifest (for directories)
- * replace-conents form (for mutable files)
+ * replace-contents form (for mutable files)
+
 
 Creating a Directory
 --------------------
@@ -1020,6 +1115,10 @@ Creating a Directory
  /uri/$DIRCAP page. There is a "create directory" button on the Welcome page
  to invoke this action.
 
+ This accepts a format= argument in the query string. Refer to the
+ documentation of the PUT /uri?t=mkdir operation in `Creating A
+ New Directory`_ for information on the behavior of the format= argument.
+
  If "redirect_to_result=true" is not provided (or is given a value of
  "false"), then the HTTP response body will simply be the write-cap of the
  new directory.
@@ -1029,6 +1128,11 @@ Creating a Directory
  This creates a new empty directory as a child of the designated SUBDIR. This
  will create additional intermediate directories as necessary.
 
+ This accepts a format= argument in the query string. Refer to the
+ documentation of POST /uri/$DIRCAP/[SUBDIRS../]?t=mkdir&name=CHILDNAME in
+ `Creating a New Directory`_ for information on the behavior of the format=
+ argument.
+
  If a "when_done=URL" argument is provided, the HTTP response will cause the
  web browser to redirect to the given URL. This provides a convenient way to
  return the browser to the directory that was just modified. Without a
@@ -1065,11 +1169,9 @@ Uploading a File
  about which storage servers were used for the upload, how long each
  operation took, etc.
 
- If a "mutable=true" argument is provided, the operation will create a
- mutable file, and the response body will contain the write-cap instead of
- the upload results page. The default is to create an immutable file,
- returning the upload results page as a response.
-
+ This accepts format= and mutable=true query string arguments. Refer to
+ `Writing/Uploading a File`_ for information on the behavior of format= and
+ mutable=true.
 
 ``POST /uri/$DIRCAP/[SUBDIRS../]?t=upload``
 
@@ -1105,9 +1207,9 @@ Uploading a File
  /uri/$DIRCAP/[SUBDIRS../]", it is likely that the parent directory will
  already exist.
 
- If a "mutable=true" argument is provided, any new file that is created will
- be a mutable file instead of an immutable one. <input type="checkbox"
name="mutable" /> will give the user a way to set this option.
+ This accepts format= and mutable=true query string arguments. Refer to
+ `Writing/Uploading a File`_ for information on the behavior of format= and
mutable=true.
 
  If a "when_done=URL" argument is provided, the HTTP response will cause the
  web browser to redirect to the given URL. This provides a convenient way to
@@ -1131,6 +1233,7 @@ Uploading a File
  the "PUT /uri/$FILECAP" form, but uses a POST for the benefit of HTML forms
  in a web browser.
 
+
 Attaching An Existing File Or Directory (by URI)
 ------------------------------------------------
 
@@ -1140,7 +1243,7 @@ Attaching An Existing File Or Directory (by URI)
  directory, with a specified child name. This behaves much like the PUT t=uri
  operation, and is a lot like a UNIX hardlink. It is subject to the same
  restrictions as that operation on the use of cap formats unknown to the
- webapi server.
+ web-API server.
 
  This will create additional intermediate directories as necessary, although
  since it is expected to be triggered by a form that was retrieved by "GET
@@ -1149,11 +1252,14 @@ Attaching An Existing File Or Directory (by URI)
 
  This accepts the same replace= argument as POST t=upload.
 
-Deleting A Child
-----------------
+
+Unlinking a Child
+-----------------
 
 ``POST /uri/$DIRCAP/[SUBDIRS../]?t=delete&name=CHILDNAME``
 
+``POST /uri/$DIRCAP/[SUBDIRS../]?t=unlink&name=CHILDNAME``    (Tahoe >= v1.9)
+
  This instructs the node to remove a child object (file or subdirectory) from
  the given directory, which must be mutable. Note that the entire subtree is
  unlinked from the parent. Unlike deleting a subdirectory in a UNIX local
@@ -1161,7 +1267,12 @@ Deleting A Child
  into the subtree will see that the child subdirectories are not modified by
  this operation. Only the link from the given directory to its child is severed.
 
-Renaming A Child
+ In Tahoe-LAFS v1.9.0 and later, t=unlink can be used as a synonym for t=delete.
+ If interoperability with older web-API servers is required, t=delete should
+ be used.
+
+
+Renaming a Child
 ----------------
 
 ``POST /uri/$DIRCAP/[SUBDIRS../]?t=rename&from_name=OLD&to_name=NEW``
@@ -1171,8 +1282,73 @@ Renaming A Child
  same child-cap under the new name, except that it preserves metadata. This
  operation cannot move the child to a different directory.
 
- This operation will replace any existing child of the new name, making it
- behave like the UNIX "``mv -f``" command.
+ The default behavior is to overwrite any existing link at the destination
+ (replace=true). To prevent this (and make the operation return an error
+ instead of overwriting), add a "replace=false" argument. With replace=false,
+ this operation will return an HTTP 409 "Conflict" error if the destination
+ is not the same link as the source and there is already a link at the
+ destination, rather than overwriting the existing link. To allow the
+ operation to overwrite a link to a file, but return an HTTP 409 error when
+ trying to overwrite a link to a directory, use "replace=only-files" (this
+ behavior is closer to the traditional UNIX "mv" command). Note that "true",
+ "t", and "1" are all synonyms for "True"; "false", "f", and "0" are synonyms
+ for "False"; and the parameter is case-insensitive.
+
+
+Relinking ("Moving") a Child
+----------------------------
+
+``POST /uri/$DIRCAP/[SUBDIRS../]?t=relink&from_name=OLD&to_dir=$NEWDIRCAP/[NEWSUBDIRS../]&to_name=NEW``
+ ``[&replace=true|false|only-files]``    (Tahoe >= v1.10)
+
+ This instructs the node to move a child of the given source directory, into
+ a different directory and/or to a different name. The command is named
+ ``relink`` because what it does is add a new link to the child from the new
+ location, then remove the old link. Nothing is actually "moved": the child
+ is still reachable through any path from which it was formerly reachable,
+ and the storage space occupied by its ciphertext is not affected.
+
+ The source and destination directories must be writeable. If {{{to_dir}}} is
+ not present, the child link is renamed within the same directory. If
+ {{{to_name}}} is not present then it defaults to {{{from_name}}}. If the
+ destination link (directory and name) is the same as the source link, the
+ operation has no effect.
+
+ Metadata from the source directory entry is preserved. Multiple levels of
+ descent in the source and destination paths are supported.
+
+ This operation will return an HTTP 404 "Not Found" error if
+ ``$DIRCAP/[SUBDIRS../]``, the child being moved, or the destination
+ directory does not exist. It will return an HTTP 400 "Bad Request" error
+ if any entry in the source or destination paths is not a directory.
+
+ The default behavior is to overwrite any existing link at the destination
+ (replace=true). To prevent this (and make the operation return an error
+ instead of overwriting), add a "replace=false" argument. With replace=false,
+ this operation will return an HTTP 409 "Conflict" error if the destination
+ is not the same link as the source and there is already a link at the
+ destination, rather than overwriting the existing link. To allow the
+ operation to overwrite a link to a file, but return an HTTP 409 error when
+ trying to overwrite a link to a directory, use "replace=only-files" (this
+ behavior is closer to the traditional UNIX "mv" command). Note that "true",
+ "t", and "1" are all synonyms for "True"; "false", "f", and "0" are synonyms
+ for "False"; and the parameter is case-insensitive.
+
+ When relinking into a different directory, for safety, the child link is
+ not removed from the old directory until it has been successfully added to
+ the new directory. This implies that in case of a crash or failure, the
+ link to the child will not be lost, but it could be linked at both the old
+ and new locations.
+
+ The source link should not be the same as any link (directory and child name)
+ in the ``to_dir`` path. This restriction is not enforced, but it may be
+ enforced in a future version. If it were violated then the result would be
+ to create a cycle in the directory structure that is not necessarily reachable
+ from the root of the destination path (``$NEWDIRCAP``), which could result in
+ data loss, as described in ticket `#943`_.
+
+.. _`#943`: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/943
+
 
 Other Utilities
 ---------------
@@ -1195,6 +1371,8 @@ Other Utilities
   functionality described above, with the provided $CHILDNAME present in the
   'from_name' field of that form. I.e. this presents a form offering to
   rename $CHILDNAME, requesting the new name, and submitting POST rename.
+  This same URL format can also be used with "move-form" with the expected
+  results.
 
 ``GET /uri/$DIRCAP/[SUBDIRS../]CHILDNAME?t=uri``
 
@@ -1206,6 +1384,7 @@ Other Utilities
  If the object is an immutable file, this will return the same value as
  t=uri.
 
+
 Debugging and Testing Features
 ------------------------------
 
@@ -1233,58 +1412,64 @@ mainly intended for developers.
  dictionary with the following keys::
 
   storage-index: a base32-encoded string with the objects's storage index,
-                                or an empty string for LIT files
+                 or an empty string for LIT files
   summary: a string, with a one-line summary of the stats of the file
   results: a dictionary that describes the state of the file. For LIT files,
-                  this dictionary has only the 'healthy' key, which will always be
-                  True. For distributed files, this dictionary has the following
-                  keys:
-       count-shares-good: the number of good shares that were found
-       count-shares-needed: 'k', the number of shares required for recovery
-       count-shares-expected: 'N', the number of total shares generated
-       count-good-share-hosts: this was intended to be the number of distinct
-                                                       storage servers with good shares. It is currently
-                                                       (as of Tahoe-LAFS v1.8.0) computed incorrectly;
-                                                       see ticket #1115.
-       count-wrong-shares: for mutable files, the number of shares for
-                                               versions other than the 'best' one (highest
-                                               sequence number, highest roothash). These are
-                                               either old ...
-       count-recoverable-versions: for mutable files, the number of
-                                                               recoverable versions of the file. For
-                                                               a healthy file, this will equal 1.
-       count-unrecoverable-versions: for mutable files, the number of
-                                                                 unrecoverable versions of the file.
-                                                                 For a healthy file, this will be 0.
-       count-corrupt-shares: the number of shares with integrity failures
-       list-corrupt-shares: a list of "share locators", one for each share
-                                                that was found to be corrupt. Each share locator
-                                                is a list of (serverid, storage_index, sharenum).
-       needs-rebalancing: (bool) True if there are multiple shares on a single
-                                          storage server, indicating a reduction in reliability
-                                          that could be resolved by moving shares to new
-                                          servers.
-       servers-responding: list of base32-encoded storage server identifiers,
-                                               one for each server which responded to the share
-                                               query.
-       healthy: (bool) True if the file is completely healthy, False otherwise.
-                        Healthy files have at least N good shares. Overlapping shares
-                        do not currently cause a file to be marked unhealthy. If there
-                        are at least N good shares, then corrupt shares do not cause the
-                        file to be marked unhealthy, although the corrupt shares will be
-                        listed in the results (list-corrupt-shares) and should be manually
-                        removed to wasting time in subsequent downloads (as the
-                        downloader rediscovers the corruption and uses alternate shares).
-                        Future compatibility: the meaning of this field may change to
-                        reflect whether the servers-of-happiness criterion is met
-                        (see ticket #614).
-       sharemap: dict mapping share identifier to list of serverids
-                         (base32-encoded strings). This indicates which servers are
-                         holding which shares. For immutable files, the shareid is
-                         an integer (the share number, from 0 to N-1). For
-                         immutable files, it is a string of the form
-                         'seq%d-%s-sh%d', containing the sequence number, the
-                         roothash, and the share number.
+           this dictionary has only the 'healthy' key, which will always be
+           True. For distributed files, this dictionary has the following
+           keys:
+    count-happiness: the servers-of-happiness level of the file, as
+                     defined in `docs/specifications/servers-of-happiness.rst`_.
+    count-shares-good: the number of good shares that were found
+    count-shares-needed: 'k', the number of shares required for recovery
+    count-shares-expected: 'N', the number of total shares generated
+    count-good-share-hosts: the number of distinct storage servers with
+                            good shares. Note that a high value does not
+                            necessarily imply good share distribution,
+                            because some of these servers may only hold
+                            duplicate shares.
+    count-wrong-shares: for mutable files, the number of shares for
+                        versions other than the 'best' one (highest
+                        sequence number, highest roothash). These are
+                        either old, or created by an uncoordinated or
+                        not fully successful write.
+    count-recoverable-versions: for mutable files, the number of
+                                recoverable versions of the file. For
+                                a healthy file, this will equal 1.
+    count-unrecoverable-versions: for mutable files, the number of
+                                  unrecoverable versions of the file.
+                                  For a healthy file, this will be 0.
+    count-corrupt-shares: the number of shares with integrity failures
+    list-corrupt-shares: a list of "share locators", one for each share
+                         that was found to be corrupt. Each share locator
+                         is a list of (serverid, storage_index, sharenum).
+    servers-responding: list of base32-encoded storage server identifiers,
+                        one for each server which responded to the share
+                        query.
+    healthy: (bool) True if the file is completely healthy, False otherwise.
+             Healthy files have at least N good shares. Overlapping shares
+             do not currently cause a file to be marked unhealthy. If there
+             are at least N good shares, then corrupt shares do not cause the
+             file to be marked unhealthy, although the corrupt shares will be
+             listed in the results (list-corrupt-shares) and should be manually
+             removed to wasting time in subsequent downloads (as the
+             downloader rediscovers the corruption and uses alternate shares).
+             Future compatibility: the meaning of this field may change to
+             reflect whether the servers-of-happiness criterion is met
+             (see ticket #614).
+    sharemap: dict mapping share identifier to list of serverids
+              (base32-encoded strings). This indicates which servers are
+              holding which shares. For immutable files, the shareid is
+              an integer (the share number, from 0 to N-1). For
+              immutable files, it is a string of the form
+              'seq%d-%s-sh%d', containing the sequence number, the
+              roothash, and the share number.
+
+Before Tahoe-LAFS v1.11, the `results` dictionary also had a `needs-rebalancing`
+field, but that has been removed since it was computed incorrectly.
+
+.. _`docs/specifications/servers-of-happiness.rst`: ../specifications/servers-of-happiness.rst
+
 
 ``POST $URL?t=start-deep-check``    (must add &ophandle=XYZ)
 
@@ -1319,31 +1504,31 @@ mainly intended for developers.
  machine-readable JSON dictionary with the following keys::
 
   finished: a boolean, True if the operation is complete, else False. Some
-                       of the remaining keys may not be present until the operation
-                       is complete.
+            of the remaining keys may not be present until the operation
+            is complete.
   root-storage-index: a base32-encoded string with the storage index of the
-                                         starting point of the deep-check operation
+                      starting point of the deep-check operation
   count-objects-checked: count of how many objects were checked. Note that
-                                                non-distributed objects (i.e. small immutable LIT
-                                                files) are not checked, since for these objects,
-                                                the data is contained entirely in the URI.
+                         non-distributed objects (i.e. small immutable LIT
+                         files) are not checked, since for these objects,
+                         the data is contained entirely in the URI.
   count-objects-healthy: how many of those objects were completely healthy
   count-objects-unhealthy: how many were damaged in some way
   count-corrupt-shares: how many shares were found to have corruption,
-                                               summed over all objects examined
+                        summed over all objects examined
   list-corrupt-shares: a list of "share identifiers", one for each share
-                                          that was found to be corrupt. Each share identifier
-                                          is a list of (serverid, storage_index, sharenum).
+                       that was found to be corrupt. Each share identifier
+                       is a list of (serverid, storage_index, sharenum).
   list-unhealthy-files: a list of (pathname, check-results) tuples, for
-                                               each file that was not fully healthy. 'pathname' is
-                                               a list of strings (which can be joined by "/"
-                                               characters to turn it into a single string),
-                                               relative to the directory on which deep-check was
-                                               invoked. The 'check-results' field is the same as
-                                               that returned by t=check&output=JSON, described
-                                               above.
+                        each file that was not fully healthy. 'pathname' is
+                        a list of strings (which can be joined by "/"
+                        characters to turn it into a single string),
+                        relative to the directory on which deep-check was
+                        invoked. The 'check-results' field is the same as
+                        that returned by t=check&output=JSON, described
+                        above.
   stats: a dictionary with the same keys as the t=start-deep-stats command
-                (described below)
+         (described below)
 
 ``POST $URL?t=stream-deep-check``
 
@@ -1411,21 +1596,21 @@ mainly intended for developers.
  will contain the following keys::
 
   storage-index: a base32-encoded string with the objects's storage index,
-                                or an empty string for LIT files
+                 or an empty string for LIT files
   repair-attempted: (bool) True if repair was attempted
   repair-successful: (bool) True if repair was attempted and the file was
-                                        fully healthy afterwards. False if no repair was
-                                        attempted, or if a repair attempt failed.
+                     fully healthy afterwards. False if no repair was
+                     attempted, or if a repair attempt failed.
   pre-repair-results: a dictionary that describes the state of the file
-                                         before any repair was performed. This contains exactly
-                                         the same keys as the 'results' value of the t=check
-                                         response, described above.
+                      before any repair was performed. This contains exactly
+                      the same keys as the 'results' value of the t=check
+                      response, described above.
   post-repair-results: a dictionary that describes the state of the file
-                                          after any repair was performed. If no repair was
-                                          performed, post-repair-results and pre-repair-results
-                                          will be the same. This contains exactly the same keys
-                                          as the 'results' value of the t=check response,
-                                          described above.
+                       after any repair was performed. If no repair was
+                       performed, post-repair-results and pre-repair-results
+                       will be the same. This contains exactly the same keys
+                       as the 'results' value of the t=check response,
+                       described above.
 
 ``POST $URL?t=start-deep-check&repair=true``    (must add &ophandle=XYZ)
 
@@ -1443,44 +1628,44 @@ mainly intended for developers.
 
   finished: (bool) True if the operation has completed, else False
   root-storage-index: a base32-encoded string with the storage index of the
-                                         starting point of the deep-check operation
+                      starting point of the deep-check operation
   count-objects-checked: count of how many objects were checked
 
   count-objects-healthy-pre-repair: how many of those objects were completely
-                                                                       healthy, before any repair
+                                    healthy, before any repair
   count-objects-unhealthy-pre-repair: how many were damaged in some way
   count-objects-healthy-post-repair: how many of those objects were completely
-                                                                         healthy, after any repair
+                                      healthy, after any repair
   count-objects-unhealthy-post-repair: how many were damaged in some way
 
   count-repairs-attempted: repairs were attempted on this many objects.
   count-repairs-successful: how many repairs resulted in healthy objects
   count-repairs-unsuccessful: how many repairs resulted did not results in
-                                                         completely healthy objects
+                              completely healthy objects
   count-corrupt-shares-pre-repair: how many shares were found to have
-                                                                  corruption, summed over all objects
-                                                                  examined, before any repair
+                                   corruption, summed over all objects
+                                   examined, before any repair
   count-corrupt-shares-post-repair: how many shares were found to have
-                                                                       corruption, summed over all objects
-                                                                       examined, after any repair
+                                    corruption, summed over all objects
+                                    examined, after any repair
   list-corrupt-shares: a list of "share identifiers", one for each share
-                                          that was found to be corrupt (before any repair).
-                                          Each share identifier is a list of (serverid,
-                                          storage_index, sharenum).
+                       that was found to be corrupt (before any repair).
+                       Each share identifier is a list of (serverid,
+                       storage_index, sharenum).
   list-remaining-corrupt-shares: like list-corrupt-shares, but mutable shares
-                                                                that were successfully repaired are not
-                                                                included. These are shares that need
-                                                                manual processing. Since immutable shares
-                                                                cannot be modified by clients, all corruption
-                                                                in immutable shares will be listed here.
+                                 that were successfully repaired are not
+                                 included. These are shares that need
+                                 manual processing. Since immutable shares
+                                 cannot be modified by clients, all corruption
+                                 in immutable shares will be listed here.
   list-unhealthy-files: a list of (pathname, check-results) tuples, for
-                                               each file that was not fully healthy. 'pathname' is
-                                               relative to the directory on which deep-check was
-                                               invoked. The 'check-results' field is the same as
-                                               that returned by t=check&repair=true&output=JSON,
-                                               described above.
+                        each file that was not fully healthy. 'pathname' is
+                        relative to the directory on which deep-check was
+                        invoked. The 'check-results' field is the same as
+                        that returned by t=check&repair=true&output=JSON,
+                        described above.
   stats: a dictionary with the same keys as the t=start-deep-stats command
-                (described below)
+         (described below)
 
 ``POST $URL?t=stream-deep-check&repair=true``
 
@@ -1536,7 +1721,7 @@ mainly intended for developers.
   verifycaps: list of (printable) verify cap strings
   storage-index: list of (base32) storage index strings
   stats: a dictionary with the same keys as the t=start-deep-stats command
-                (described below)
+         (described below)
 
 ``POST $DIRURL?t=start-deep-size``   (must add &ophandle=XYZ)
 
@@ -1574,8 +1759,8 @@ mainly intended for developers.
   size-literal-files: same, for LIT files
   size-directories: size of directories (includes size-literal-files)
   size-files-histogram: list of (minsize, maxsize, count) buckets,
-                                               with a histogram of filesizes, 5dB/bucket,
-                                               for both literal and immutable files
+                        with a histogram of filesizes, 5dB/bucket,
+                        for both literal and immutable files
   largest-directory: number of children in the largest directory
   largest-immutable-file: number of bytes in the largest CHK file
 
@@ -1637,6 +1822,7 @@ mainly intended for developers.
  was untraversable, since the manifest entry is emitted to the HTTP response
  body before the child is traversed.
 
+
 Other Useful Pages
 ==================
 
@@ -1684,11 +1870,11 @@ This is the "Welcome Page", and contains a few distinct sections::
   progress-hash (float): 1.0 when the file has been hashed
   progress-ciphertext (float): 1.0 when the file has been encrypted.
   progress-encode-push (float): 1.0 when the file has been encoded and
-                                                               pushed to the storage servers. For helper
-                                                               uploads, the ciphertext value climbs to 1.0
-                                                               first, then encoding starts. For unassisted
-                                                               uploads, ciphertext and encode-push progress
-                                                               will climb at the same pace.
+                                pushed to the storage servers. For helper
+                                uploads, the ciphertext value climbs to 1.0
+                                first, then encoding starts. For unassisted
+                                uploads, ciphertext and encode-push progress
+                                will climb at the same pace.
 
  The "download" op-dict will contain the following keys::
 
@@ -1704,17 +1890,6 @@ This is the "Welcome Page", and contains a few distinct sections::
  implementation hashes synchronously, so clients will probably never see
  progress-hash!=1.0).
 
-``GET /provisioning/``
-
- This page provides a basic tool to predict the likely storage and bandwidth
- requirements of a large Tahoe grid. It provides forms to input things like
- total number of users, number of files per user, average file size, number
- of servers, expansion ratio, hard drive failure rate, etc. It then provides
- numbers like how many disks per server will be needed, how many read
- operations per second should be expected, and the likely MTBF for files in
- the grid. This information is very preliminary, and the model upon which it
- is based still needs a lot of work.
-
 ``GET /helper_status/``
 
  If the node is running a helper (i.e. if [helper]enabled is set to True in
@@ -1798,18 +1973,18 @@ This is the "Welcome Page", and contains a few distinct sections::
 Static Files in /public_html
 ============================
 
-The webapi server will take any request for a URL that starts with /static
+The web-API server will take any request for a URL that starts with /static
 and serve it from a configurable directory which defaults to
 $BASEDIR/public_html . This is configured by setting the "[node]web.static"
 value in $BASEDIR/tahoe.cfg . If this is left at the default value of
-"public_html", then http://localhost:3456/static/subdir/foo.html will be
+"public_html", then http://127.0.0.1:3456/static/subdir/foo.html will be
 served with the contents of the file $BASEDIR/public_html/subdir/foo.html .
 
 This can be useful to serve a javascript application which provides a
-prettier front-end to the rest of the Tahoe webapi.
+prettier front-end to the rest of the Tahoe web-API.
 
 
-Safety and security issues -- names vs. URIs
+Safety and Security Issues -- Names vs. URIs
 ============================================
 
 Summary: use explicit file- and dir- caps whenever possible, to reduce the
@@ -1852,7 +2027,7 @@ parent directory, so it isn't any harder to use the URI for this purpose.
 
 The read and write caps in a given directory node are separate URIs, and
 can't be assumed to point to the same object even if they were retrieved in
-the same operation (although the webapi server attempts to ensure this
+the same operation (although the web-API server attempts to ensure this
 in most cases). If you need to rely on that property, you should explicitly
 verify it. More generally, you should not make assumptions about the
 internal consistency of the contents of mutable directories. As a result
@@ -1865,6 +2040,7 @@ In general, use names if you want "whatever object (whether file or
 directory) is found by following this name (or sequence of names) when my
 request reaches the server". Use URIs if you want "this particular object".
 
+
 Concurrency Issues
 ==================
 
@@ -1897,29 +2073,78 @@ Coordination Directive.
 
 Tahoe nodes implement internal serialization to make sure that a single Tahoe
 node cannot conflict with itself. For example, it is safe to issue two
-directory modification requests to a single tahoe node's webapi server at the
+directory modification requests to a single tahoe node's web-API server at the
 same time, because the Tahoe node will internally delay one of them until
 after the other has finished being applied. (This feature was introduced in
 Tahoe-1.1; back with Tahoe-1.0 the web client was responsible for serializing
 web requests themselves).
 
 For more details, please see the "Consistency vs Availability" and "The Prime
-Coordination Directive" sections of `mutable.rst <../specifications/mutable.rst>`_.
+Coordination Directive" sections of mutable.rst_.
+
+.. _mutable.rst: ../specifications/mutable.rst
+
+
+Access Blacklist
+================
+
+Gateway nodes may find it necessary to prohibit access to certain files. The
+web-API has a facility to block access to filecaps by their storage index,
+returning a 403 "Forbidden" error instead of the original file.
+
+This blacklist is recorded in $NODEDIR/access.blacklist, and contains one
+blocked file per line. Comment lines (starting with ``#``) are ignored. Each
+line consists of the storage-index (in the usual base32 format as displayed
+by the "More Info" page, or by the "tahoe debug dump-cap" command), followed
+by whitespace, followed by a reason string, which will be included in the 403
+error message. This could hold a URL to a page that explains why the file is
+blocked, for example.
+
+So for example, if you found a need to block access to a file with filecap
+``URI:CHK:n7r3m6wmomelk4sep3kw5cvduq:os7ijw5c3maek7pg65e5254k2fzjflavtpejjyhshpsxuqzhcwwq:3:20:14861``,
+you could do the following::
+
+ tahoe debug dump-cap URI:CHK:n7r3m6wmomelk4sep3kw5cvduq:os7ijw5c3maek7pg65e5254k2fzjflavtpejjyhshpsxuqzhcwwq:3:20:14861
+ -> storage index: whpepioyrnff7orecjolvbudeu
+ echo "whpepioyrnff7orecjolvbudeu my puppy told me to" >>$NODEDIR/access.blacklist
+ tahoe restart $NODEDIR
+ tahoe get URI:CHK:n7r3m6wmomelk4sep3kw5cvduq:os7ijw5c3maek7pg65e5254k2fzjflavtpejjyhshpsxuqzhcwwq:3:20:14861
+ -> error, 403 Access Prohibited: my puppy told me to
+
+The ``access.blacklist`` file will be checked each time a file or directory
+is accessed: the file's ``mtime`` is used to decide whether it need to be
+reloaded. Therefore no node restart is necessary when creating the initial
+blacklist, nor when adding second, third, or additional entries to the list.
+When modifying the file, be careful to update it atomically, otherwise a
+request may arrive while the file is only halfway written, and the partial
+file may be incorrectly parsed.
+
+The blacklist is applied to all access paths (including SFTP, FTP, and CLI
+operations), not just the web-API. The blacklist also applies to directories.
+If a directory is blacklisted, the gateway will refuse access to both that
+directory and any child files/directories underneath it, when accessed via
+"DIRCAP/SUBDIR/FILENAME" -style URLs. Users who go directly to the child
+file/dir will bypass the blacklist.
+
+The node will log the SI of the file being blocked, and the reason code, into
+the ``logs/twistd.log`` file.
 
 
 .. [1] URLs and HTTP and UTF-8, Oh My
 
  HTTP does not provide a mechanism to specify the character set used to
- encode non-ascii names in URLs (rfc2396#2.1). We prefer the convention that
- the filename= argument shall be a URL-encoded UTF-8 encoded unicode object.
- For example, suppose we want to provoke the server into using a filename of
- "f i a n c e-acute e" (i.e. F I A N C U+00E9 E). The UTF-8 encoding of this
- is 0x66 0x69 0x61 0x6e 0x63 0xc3 0xa9 0x65 (or "fianc\xC3\xA9e", as python's
- repr() function would show). To encode this into a URL, the non-printable
- characters must be escaped with the urlencode '%XX' mechansim, giving us
- "fianc%C3%A9e". Thus, the first line of the HTTP request will be "GET
- /uri/CAP...?save=true&filename=fianc%C3%A9e HTTP/1.1". Not all browsers
- provide this: IE7 uses the Latin-1 encoding, which is fianc%E9e.
+ encode non-ASCII names in URLs (`RFC3986#2.1`_).  We prefer the convention
+ that the ``filename=`` argument shall be a URL-escaped UTF-8 encoded Unicode
+ string.  For example, suppose we want to provoke the server into using a
+ filename of "f i a n c e-acute e" (i.e. f i a n c U+00E9 e). The UTF-8
+ encoding of this is 0x66 0x69 0x61 0x6e 0x63 0xc3 0xa9 0x65 (or
+ "fianc\\xC3\\xA9e", as python's ``repr()`` function would show). To encode
+ this into a URL, the non-printable characters must be escaped with the
+ urlencode ``%XX`` mechanism, giving us "fianc%C3%A9e". Thus, the first line
+ of the HTTP request will be "``GET
+ /uri/CAP...?save=true&filename=fianc%C3%A9e HTTP/1.1``". Not all browsers
+ provide this: IE7 by default uses the Latin-1 encoding, which is "fianc%E9e"
+ (although it has a configuration option to send URLs as UTF-8).
 
  The response header will need to indicate a non-ASCII filename. The actual
  mechanism to do this is not clear. For ASCII filenames, the response header
@@ -1927,37 +2152,41 @@ Coordination Directive" sections of `mutable.rst <../specifications/mutable.rst>
 
   Content-Disposition: attachment; filename="english.txt"
 
- If Tahoe were to enforce the utf-8 convention, it would need to decode the
- URL argument into a unicode string, and then encode it back into a sequence
+ If Tahoe were to enforce the UTF-8 convention, it would need to decode the
+ URL argument into a Unicode string, and then encode it back into a sequence
  of bytes when creating the response header. One possibility would be to use
- unencoded utf-8. Developers suggest that IE7 might accept this::
+ unencoded UTF-8. Developers suggest that IE7 might accept this::
 
   #1: Content-Disposition: attachment; filename="fianc\xC3\xA9e"
     (note, the last four bytes of that line, not including the newline, are
     0xC3 0xA9 0x65 0x22)
 
- `RFC2231#4 <http://tools.ietf.org/html/rfc2231#section-4>`_
- (dated 1997): suggests that the following might work, and
- `some developers have reported <http://markmail.org/message/dsjyokgl7hv64ig3>`_
- that it is supported by firefox (but not IE7)::
+ `RFC2231#4`_ (dated 1997): suggests that the following might work, and `some
+ developers have reported`_ that it is supported by Firefox (but not IE7)::
 
   #2: Content-Disposition: attachment; filename*=utf-8''fianc%C3%A9e
 
- My reading of `RFC2616#19.5.1 <http://tools.ietf.org/html/rfc2616#section-19.5.1>`_
- (which defines Content-Disposition) says that the filename= parameter is
- defined to be wrapped in quotes (presumably to allow spaces without breaking
the parsing of subsequent parameters), which would give us::
+ My reading of `RFC2616#19.5.1`_ (which defines Content-Disposition) says
+ that the filename= parameter is defined to be wrapped in quotes (presumably
+ to allow spaces without breaking the parsing of subsequent parameters),
+ which would give us::
 
   #3: Content-Disposition: attachment; filename*=utf-8''"fianc%C3%A9e"
 
  However this is contrary to the examples in the email thread listed above.
 
  Developers report that IE7 (when it is configured for UTF-8 URL encoding,
- which is not the default in asian countries), will accept::
+ which is not the default in Asian countries), will accept::
 
   #4: Content-Disposition: attachment; filename=fianc%C3%A9e
 
  However, for maximum compatibility, Tahoe simply copies bytes from the URL
- into the response header, rather than enforcing the utf-8 convention. This
+ into the response header, rather than enforcing the UTF-8 convention. This
  means it does not try to decode the filename from the URL argument, nor does
  it encode the filename into the response header.
+
+.. _RFC3986#2.1: https://tools.ietf.org/html/rfc3986#section-2.1
+.. _RFC2231#4: https://tools.ietf.org/html/rfc2231#section-4
+.. _some developers have reported: http://markmail.org/message/dsjyokgl7hv64ig3
+.. _RFC2616#19.5.1: https://tools.ietf.org/html/rfc2616#section-19.5.1
+