diff --git a/.github/workflows/reusable-deploy-docs.yml b/.github/workflows/reusable-deploy-docs.yml
index 631f50951..361ad1b2e 100644
--- a/.github/workflows/reusable-deploy-docs.yml
+++ b/.github/workflows/reusable-deploy-docs.yml
@@ -23,6 +23,7 @@ jobs:
registry-url: 'https://registry.npmjs.org'
cache: 'pnpm'
- run: pnpm install
+ - run: pnpm build
- run: pnpm run lint
- run: pnpm run docs
- uses: actions/configure-pages@v2
diff --git a/packages/upload-client/src/car.js b/packages/upload-client/src/car.js
index 09a8e6ca5..44e7f6d52 100644
--- a/packages/upload-client/src/car.js
+++ b/packages/upload-client/src/car.js
@@ -64,16 +64,6 @@ export class BlockStream extends ReadableStream {
let blocksPromise = null
const getBlocksIterable = () => {
if (blocksPromise) return blocksPromise
- // FIXME: remove when resolved: https://github.com/nodejs/node/issues/48916
- /* c8 ignore next 10 */
- if (parseInt(globalThis.process?.versions?.node) > 18) {
- blocksPromise = (async () => {
- // @ts-expect-error
- const bytes = await car.arrayBuffer()
- return CarBlockIterator.fromBytes(new Uint8Array(bytes))
- })()
- return blocksPromise
- }
blocksPromise = CarBlockIterator.fromIterable(toIterable(car.stream()))
return blocksPromise
}
diff --git a/packages/w3up-client/README.md b/packages/w3up-client/README.md
index 05d80a734..49106e24a 100644
--- a/packages/w3up-client/README.md
+++ b/packages/w3up-client/README.md
@@ -19,6 +19,8 @@ questions!
This library is the user-facing "porcelain" client for interacting with w3up services from JavaScript. It wraps the lower-level [`@web3-storage/access`][access-client-github] and [`@web3-storage/upload-client`][upload-client-github] client packages, which target individual w3up services. We recommend using `w3up-client` instead of using those "plumbing" packages directly, but you may find them useful if you need more context on w3up's architecture and internals.
+**`w3up-client` requires Node 18 or higher**.
+
> β οΈβ __Public Data__ π: All data uploaded to w3up is available to anyone who requests it using the correct CID. Do not store any private or sensitive information in an unencrypted form using w3up.
> β οΈβ __Permanent Data__ βΎοΈ: Removing files from w3up will remove them from the file listing for your account, but that doesnβt prevent nodes on the decentralized storage network from retaining copies of the data indefinitely. Do not use w3up for data that may need to be permanently deleted in the future.
@@ -47,7 +49,7 @@ npm install @web3-storage/w3up-client
[API Reference](#api)
-Most users' usage of `w3up-client` will be for interacting with web3.storage, a hosted storage product that developed w3up for their upload APIs. However, any user that has an implementation of w3up ([specs](https://github.com/web3-storage/specs), [protocol](https://github.com/web3-storage/w3protocol/)) can configure `w3up-client` for their usage.
+Most users' usage of `w3up-client` will be for interacting with web3.storage, a hosted storage product that developed w3up for their upload APIs. However, any user that has an implementation of w3up ([specs](https://github.com/web3-storage/specs), [protocol](https://github.com/web3-storage/w3up)) can configure `w3up-client` for their usage.
For authorization, w3up services use [ucanto][ucanto], a Remote Procedure Call (RPC) framework built around [UCAN](https://ucan.xzy), or User Controlled Authorization Networks. UCANs are a powerful capability-based authorization system that allows fine-grained sharing of permissions through a process called _delegation_ on top of [public key cryptography](https://en.wikipedia.org/wiki/Public-key_cryptography). See our [intro to UCAN blog post](https://blog.web3.storage/posts/intro-to-ucan) for an overview of UCAN.
diff --git a/spec/access-identify.md b/spec/access-identify.md
deleted file mode 100644
index 549a9a183..000000000
--- a/spec/access-identify.md
+++ /dev/null
@@ -1,305 +0,0 @@
-## `access/identify`
-
-Upload protocol defines [access/identify][] capability which is very flexible yet powerful so it can be very confusing. This document attempts to wolk through some user stories to try and clarify.
-
-#### identify with email
-
-"Accounting" service MAY delegate to other "verifier" service(s) to do out of band user verification e.g. sign-in via email link style flow.
-
-To do so the _accounting_ service must delegate a capability to a _verifier_ service which will allow it to:
-
-1. Create accounts under the `did:email:` namespace.
-2. Associate other DIDs with accounts under `did:email:` namespace.
-
-**Accounting must trust the verifier service. A malicious verifier could get control of other accounts.**
-
-```js
-// The account service signs this with it's key, and sends it to the verifier service
-{
- issuer: "did:key:zAccount",
- audience: "did:key:zVerify",
- capabilities: [
- {
- can: "access/identify",
- with: "did:email:*"
- }
- ]
-}
-```
-
-Alice uses an example service _web3.app_. On first load, the app generates a keypair for Alice locally, and encodes the public key as `did:key:zAlice` DID.
-
-_web3.app_ supports email login through the `did:key:zVerify` service. When Alice provides an email address, the app will send a request to `did:key:zVerify`.
-
-```js
-// web3.app signs this with Alice's key and sends it to the verifier service
-{
- issuer: "did:key:zAlice",
- audience: "did:key:zVerify",
- capabilities: [
- {
- can: "access/identify",
- with: "mailto:a@li.ce"
- }
- ]
-}
-```
-
-Verifier service `did:key:zVerify` will delegate capability it got from `did:key:zAccount` to `did:key:zAlice` and embed it in a confiramtion emali link
-
-```js
-{
- issuer: "did:key:zVerify",
- audience: "did:key:zAlice",
- capabilities: [
- {
- can: "access/identify",
- with: "did:email:a@li.ce"
- }
- ],
- "proofs": [
- {
- issuer: "did:key:zAccount",
- audience: "did:key:zVerify",
- capabilities: [
- {
- can: "access/identify",
- with: "did:email:*"
- }
- ]
- }
- ]
-}
-```
-
-Email link takes Alice back to web3.app which extracts embedded UCAN delegation which it invokes to register `did:key:zAlice` with `did:key:zAccount`.
-
-```js
-{
- issuer: "did:key:zAlice",
- audience: "did:key:zAccount",
- capabilities: [
- {
- can: "access/identify",
- with: "did:email:a@li.ce"
- }
- ],
- proofs: [
- {
- issuer: "did:key:zVerify",
- audience: "did:key:zAlice",
- capabilities: [
- {
- can: "access/identify",
- with: "did:email:a@li.ce",
- }
- ],
- proofs: [
- {
- issuer: "did:key:zAccount",
- audience: "did:key:zVerify",
- capabilities: [
- {
- can: "access/identify",
- with: "did:email:*",
- }
- ]
- }
- ]
- }
- ]
-}
-```
-
-When accounting service receives this invocation they check they verify that `did:key:zAlice` can identify with `a@li.ce` by verifying proof chains and perform following steps
-
-1. Registers an account for her with a root did that is derived from the CID of the received invocation token `did:did:bafy..ali`
-2. Links `did:email:a@li.ce` to account DID `did:did:bafy..ali`
-3. Links `did:key:zAlice` to account DID `did:did:bafy..ali`
-
-:::info
-Derived root DID is used to allow Alice unlink `did:key:zAlice` and `did:email:a@li.ce` in the future e.g. if her key or email gets compromised
-:::
-
-### Wallet auth
-
-Mobile version of web3.app offers wallet based auth so on her phone Alice chooses to use that option. On first run app generates new did `did:key:zAli` and then asks wallet to sign ucan issued from account corresponding to `did:ethr:0xAl1ce`
-
-```js
-{
- issuer: "did:ethr:0xAl1ce",
- audience: "did:key:zAli",
- capabilities: [
- {
- can: "access/identify",
- with: "did:ethr:0xAl1ce",
- }
- ]
-}
-```
-
-web3.app then invokes issued capability in order to register new did with `did:key:zAccount`:
-
-```js
-{
- issuer: "did:key:zAli",
- audience: "did:key:zAccount",
- capabilities: [
- {
- can: "access/identify",
- with: "did:ethr:0xAl1ce",
- }
- ],
- proofs: [
- {
- issuer: "did:ethr:0xAl1ce",
- audience: "did:key:zAli",
- capabilities: [
- {
- can: "access/identify",
- with: "did:ethr:0xAl1ce",
- }
- ]
- }
- ]
-}
-```
-
-When service receives the request
-
-1. It can verify that root token was issued by the walled account.
-2. That `did:key:zAli` was delegated capability
-3. Since system does not have account for neither `did:ethr:0xAl1ce` nor `did:key:zAli` it creates new account `did:did:bafy..l1z` and links those DID with it.
-
-### Merging Acounts
-
-However Alice does not wants a separate account from the one she had on her laptop. Therefor Alice uses "link account" web3.app feature. Mobile app asks Alice to activate linking on other device and scan displayed QR code from her phone.
-
-When alice activates linking on her laptop web3.app
-
-1. Generates new keypair corrsponding to `did:key:zLink`.
-2. And delegates an `access/identify` capability for it.
-
-```js
-{
- issuer: "did:key:zAlice",
- audience: "did:key:zLink",
- capabilities: [
- {
- can: "access/identify",
- with: "did:key:zAlice",
- }
- ]
-}
-```
-
-New private key + UCAN signature are encoded in QR code and renderred on the screen.
-
-Alice scans QR code from her phone, allowing web3.app to gain control of `did:key:zALink` and capability to link with `did:key:zAlice`. So it invokes the capability:
-
-```js
-{
- issuer: "did:key:zAli",
- audience: "did:key:zAccount",
- capabilities: [
- {
- can: "access/identify",
- with: "did:key:zAlice",
- }
- ],
- proofs: [
- {
- issuer: "did:key:zLink",
- audience: "did:key:zAli",
- capabilities: [
- {
- can: "access/identify",
- with: "did:key:zAlice",
- }
- ],
- proofs: [
- {
- issuer: "did:key:zAlice",
- audience: "did:key:zLink",
- capabilities: [
- {
- can: "access/identify",
- with: "did:key:zAlice",
- }
- ]
- }
- ]
- }
- ]
-}
-```
-
-When `did:key:zAccount` receives this invocation it can verify that `did:key:zAlice` authroized `zAli` to identify with `did:key:zAlice` through `zLink` so it proceeds:
-
-1. Since `did:key:zAlice` is registered with `did:did:bafy..ali` account and `did:key:zAli` is registered with `did:did:bafy..l1z` two need to be merged so system creates new joint account derived from invocation cid `did:did:bafy..join`.
-2. Relinks all dids from both `did:did:bafy..ali ` and `did:did:bafy..l1z` to new `did:did:bafy..join` ac
-
-### identify with web proofs
-
-Bob loads web3.app and on first run it generates local keypair `did:key:zb0b`. In order to allow storing data app needs to register account with `did:key:zAccount`. Bob chooses to use keybase.io inspired web proof based identification to start an account. He clicks "identify with twitter" link which instructs Bob to tweet following message and paste a link back
-
-> I am also known as `did:key:zb0b`
-
-Bob tweets the message and pastes link back into web3.app which in turn generates a following UCAN invocation:
-
-```js
-{
- issuer: "did:key:zb0b",
- audience: "did:key:zAccount",
- capabilities: [
- {
- can: "access/identify"
- with: "did:twitter:bob"
- proof: "https://twitter.com/bob/status/997184662995849216"
- }
- ]
-}
-```
-
-`did:key:zAccount` receives invocation and verifies that:
-
-1. Twitter user `@bob` authorized itself as `did:key:zb0b` by loading URL and checking that Bob claims to be also known as `did:key:zb0b`.
-2. That issuer matches clamied `did:key:zb0b`.
-
-And if all checks out it proceeds with account registration steps:
-
-1. Derives account did from the invoction cid `did:did:bafy..6o6`.
-2. Links `did:key:zbob` with account `did:did:bafy..6o6`.
-3. Links `did:twitter:bob`
-
-#### Key recovery
-
-Bob looses access to the device with `did:key:zb0b` keypair. On a new device web3.app on first run generates new local keypair `did:key:zB06`. Bob repeats the same βidentify with twitterβ flow as before and app invokes new capability
-
-```js
-{
- issuer: "did:key:zB06",
- audience: "did:key:zAccount",
- capabilities: [
- {
- can: "access/identify"
- with: "did:twitter:bob"
- proof: "https://twitter.com/bob/status/11010011101101"
- }
- ]
-}
-```
-
-`did:key:zAccount` receives invocation and verifies that:
-
-1. Twitter user `@bob` authorized itself as `did:key:zB06` by loading URL and checking that Bob claims to be also known as `did:key:zB06`.
-2. That issuer matches clamied `did:key:zB06`.
-
-And if all checks out it proceeds with key registration steps:
-
-1. Checks if `did:twitter:bob` is already associated with some account.
-2. Since previous registration associated it with `did:did:bafy..6o6` new `did:key:zB06` key is linked to that account.
-
-Now bob can use new device with existing account
-
-[access/identify]: https://hackmd.io/UKf7w04kSzaQOGQenOofaQ#Identify
diff --git a/spec/capabilities.md b/spec/capabilities.md
deleted file mode 100644
index 809126aae..000000000
--- a/spec/capabilities.md
+++ /dev/null
@@ -1,332 +0,0 @@
-# Capabilities
-
-This reference doc contains details about each capability defined in the w3-protocol suite of services. It does not specify the exact RPC semantics for each service, for example, result schemas, possible error conditions, etc. See [services.md](./services.md) for those details.
-
-## About the definitions
-
-A capability consists of several components:
-
-- The **ability** is the "verb" of the capability, describing the action an agent can perform. For example, `store/add` allows adding CAR files to the store. Abilities are encoded into the `can` field in a UCAN delegation or invocation.
-- The **resource** is the "noun" of the capability, describing something that an agent is trying to perform an action _on_. Resources are URIs and are encoded into the `with` field of a UCAN.
-- The **caveats** are qualifiers that can constrain delegations or parameterize invocations. See below for more details. Caveats are encoded into the `nb` object field of a UCAN.
-
-In the definitions below, we identify capabilities by the ability name, which is used by the service provider to route invocations to the correct handler. The definitions include what kinds of resource URI are acceptable, as well as optional and required caveats that can be included in an invocation.
-
-The caveats are used for two complementary purposes. When used in an invocation, they act as "function parameters" for the remote procedure call, giving the capability provider the context they need to fulfill the request. For example, the `link` caveat in a `store/add` invocation specifies the CID of the CAR to be stored.
-
-When used in a delegation, caveats act as constraints on the values allowed in an invocation. For example, if a `store/add` delegation has a `size` caveat of 10MB, your invocation's `size` caveat must be less than or equal to 10MB.
-
-### Issuer and audience
-
-UCANs have a notion of "issuer" and "audience", represented by the `iss` and `aud` fields.
-
-In an invocation, the audience is the service provider, and the issuer is the agent that is making the request.
-
-In a delegation, the audience is the agent who is being delegated _to_, and the issuer is an agent who already posesses the capability and is delegating to the audience. In the common case of a single delegation from service provider to user agent, the service would be the issuer, and the user agent would be the audience.
-
-There may be multiple delegations in a chain, for example: service `A` issues a delegation to service `B` as the audience, followed by service `B` issuing a delegation to user agent `U` as the audience. To exercise the capability, `U` would issue an invocation with `A` as the audience and include the delegation chain as proof of authorization.
-
-## Accounts
-
-The `account/` namespace contains capabilities related to account identification and recovery.
-
-Note that we have recently begun referring to accounts as "memory spaces," because the word "account" has many meanings, none of which map precisely to our use case. The capabilities related to memory spaces still use the `account/` namespace, but this may change in the future. If so, this doc will be updated to reflect the change.
-
-The `account/*` capability contains (can derive) all abilities in the `account/` namespace, so long as the derived capability has the same resource URI.
-
-### `account/info`
-
-> Request information about a memory space DID.
-
-The `account/info` capability can be invoked to request information about a "memory space". The `with` resource URI identifies the space, usually with a `did:key` URI.
-
-See [services.md](./services.md) for a description of the result type and possible errors.
-
-#### Derivations
-
-`account/info` can be derived from an `account/*` or `*` capability with a matching `with` field.
-
-It can also be derived from any of the capabilities in the `store/` namespace, including [`store/*`](#store).
-
-#### Caveats
-
-`account/info` has no defined caveats.
-
-### `account/recover`
-
-> Obtain a replacement capability delegation.
-
-In the event that an agent loses the UCAN that encodes their capability delegations for a memory space (e.g. due to accidental deletion, disk corruption, etc.), they may invoke the `account/recover` capability to obtain a new delegation of the capabilities they previously had access to.
-
-The `with` resource URI of the `account/recover` invocation must contain the DID of the memory space that the agent is attempting to recover access to.
-
-The invocation must contain proof that the agent possesses the `account/recover` capability. As the agent is presumably attempting to recover because they have lost their proofs, this implies that the service must have a way to verify the identity of the agent "out of band" (not using UCAN proofs).
-
-See the [`account/recover-validation`](#accountrecover-validation) capability for more on identity validation.
-
-#### Derivations
-
-`account/recover` can be derived from an `account/*` or `*` capability with an equal `with` field.
-
-#### Caveats
-
-`account/recover` has no defined caveats.
-
-### `account/recover-validation`
-
-> Validate a registered external identity to initiate the recovery process.
-
-If an agent loses the UCAN that encodes their capability delegations for a memory space, they can initiate a recovery process by invoking the `account/recover-validation` capability.
-
-This is one of the few capabilities that can be invoked without inlcuding proof of delegation, as it is intended to be used when proofs have been lost.
-
-Instead, the service provider will verify a registered external identity (e.g. email), and will issue a delegation for the `account/recover` capability after verification is complete.
-
-#### Caveats
-
-The `account/recover-validation` invocation must include an `email` caveat containing an email address that has been previously registered (e.g. using [`voucher/redeem`](#voucherredeem)).
-
-In the future, the capability may allow validation of other types of external identity besides email. This doc will be updated to include the proper caveats when that change happens.
-
-## CAR storage
-
-The `store/` namespace contains capabilities relating to storage of CAR files.
-
-This is distinct from the `upload/` namespace, which associates root "data" CIDs with one or more CARs.
-
-The resource URI used in the `store/` capabilities is a `did:key` URI that identifies a "memory space" that acts as a destination for the stored CARs. A memory space is analagous to a bucket in S3 in that it has a unique id, groups stored objects for "directory listing" and usage/quota tracking, and is associated with a user account.
-
-### `store/*`
-
-The `store/*` capability can be delegated to a user agent, but cannot be invoked directly. Instead, it allows the audience to derive any capability in the `store/` namespace, provided the resource URI matches the one in the `store/*` capability delegation.
-
-The `store/*` capability (and all capabilities in the `store/` namespace) can be derived from a `*` "super user" capability with a matching resource URI.
-
-### `store/add`
-
-> Store a CAR file
-
-The `store/add` capability allows an agent to store a CAR file into the memory space identified by the `did:key` URI in the `with` field. The agent must precompute the CAR locally and provide the CAR's CID and size using the `nb.link` and `nb.size` fields, allowing a service to provision a write location for the agent to `PUT` or `POST` the CAR into.
-
-#### Derivations
-
-`store/add` can be derived from a `store/*` or `*` capability with a matching `with` field.
-
-#### Caveats
-
-It is possible for a service to issue a `store/add` delegation with a `link` caveat, which would restrict the user to only storing a specific CID. This is not terribly useful, however, so delegations are unlikely to contain a `link` restriction.
-
-The `size` caveat is much more likely to be included in a delegation, as service providers may want to limit the maximum CAR size that they will accept. Agents should check their delegation's `nb.size` field and ensure that they only send CARs with a size below the limit. If `nb.size` is set in the delegation, the agent must include an `nb.size` field in their invocation, with a value that is `<=` the limit set in the delegation's `nb.size` field.
-
-#### Invocation
-
-Example:
-
-```js
-{
- can: "store/add",
- with: "did:key:abc...",
- nb: {
- link: "bag...",
- size: 1234
- }
-}
-```
-
-Fields marked as "required" below must be present in the invocation, but may be absent in capability delegations.
-
-| field | value | required? | context |
-| ----------- | --------------------------------- | --------- | ------------------------------------------------------------------- |
-| `can` | `store/add` | β | The ability to add CAR data to a memory space. |
-| `with` | URI string, e.g. `did:key:123...` | β | The `did:key` URI for the CAR's destination memory space |
-| `nb.link` | CAR CID string, e.g. `bag123...` | β | CID of CAR that the user wants to store |
-| `nb.origin` | CAR CID string, e.g. `bagabc...` | β | Optional link to related CARs. See below for more details. |
-| `nb.size` | size in bytes | β | If the `size` caveat is present, the uploaded CAR must be `<= size` |
-
-The `nb.origin` field may be set to provide a link to a related CAR file. This is useful when storing large DAGs that are sharded across multiple CAR files. In this case, the agent can link each uploaded shard with a previous one. Providing the `origin` field informs the service that the CAR being stored is a shard of the larger DAG, as opposed to an intentionally partial DAG.
-
-### `store/remove`
-
-> Remove a stored CAR
-
-The `store/remove` capability can be invoked to remove a CAR file from a memory space, identified by the resource URI in the `with` field.
-
-This may or may not cause the CAR to be removed completely from Elastic IPFS; for example, if the CAR exists in other memory spaces, it will not be removed.
-
-`store/remove` will remove the CAR from the listing provided by [`store/list`](#storelist) for the memory space. Removal may also have billing implications, depending on the service provider (e.g. by affecting storage quotas).
-
-#### Derivations
-
-`store/remove` can be derived from a `store/*` or `*` capability with a matching `with` field.
-
-#### Caveats
-
-When invoking `store/remove`, the `link` caveat must be set to the CID of the CAR file to remove.
-
-If a delegation contains a `link` caveat, an invocation derived from it must have the same CAR CID in its `link` field. A delegation without a `link` caveat may be invoked with any `link` value.
-
-#### Invocation
-
-```js
-{
- can: "store/remove",
- with: "did:key:abc...",
- nb: {
- link: "bag...",
- }
-}
-```
-
-| field | value | required? | context |
-| --------- | --------------------------------- | --------- | --------------------------------------------------- |
-| `can` | `store/remove` | β | The ability to remove CAR data from a memory space. |
-| `with` | URI string, e.g. `did:key:123...` | β | The `did:key` URI for the CAR's memory space |
-| `nb.link` | CAR CID string, e.g. `bag...` | β | The CID of the CAR file to remove |
-
-### `store/list`
-
-> Obtain a list of stored CARs
-
-The `store/list` capability can be invoked to request a list of CARs in a given memory space.
-
-The `with` field of the invocation must be set to the DID of the memory space to be listed.
-
-#### Derivations
-
-`store/list` can be derived from a `store/*` or `*` capability with a matching `with` field.
-
-#### Caveats
-
-`cursor` can be set to start listing from an item in the middle of the list. Its value should be a `cursor` returned by a previous invocation of `store/list`
-`size` can be set to change the number of items returned by an `store/list` invocation
-`pre` can be set to `true` to return the page of results preceding `cursor` rather than the results after `cursor`. Defaults to `false`.
-
-| field | value | required? | context |
-| ----------- | ------------------------ | --------- | --------------------------------------------------------------- |
-| `nb.cursor` | string | β | A cursor returned by a previous invocation |
-| `nb.size` | integer | β | The maximum number of results to return |
-| `nb.pre` | boolean | β | If true, return the page of results preceding the cursor |
-
-## `upload/` namespace
-
-Capabilities relating to "uploads", which represent user data that is contained in one or more CAR files that have previously been stored using [`store/add`](#storeadd).
-
-An upload is essentially an index that maps "data CIDs" to CAR CIDs. Data CIDs are the root CID of user-uploaded data items, for example, files that have been encoded into UnixFs. A given data item may be stored in a single CAR, or it may be split into multiple CAR "shards."
-
-Similarly, a CAR can potentially contain many data items. This is true even if the CAR has only a single root CID. For example, when storing a CAR containing a nested directory structure, you could create one "upload" for the root of the directory structure, and a separate upload for a file nested inside.
-
-### `upload/*`
-
-The `upload/*` capability can be delegated to a user agent, but cannot be invoked directly. Instead, it allows the audience to derive any capability in the `upload/` namespace, provided the resource URI matches the one in the `upload/*` capability delegation.
-
-The `upload/*` capability (and all capabilities in the `upload/` namespace) can be derived from a `*` "super user" capability with a matching resource URI.
-
-### `upload/add`
-
-> Add an upload to a memory space.
-
-Can be invoked to register a given "data CID" as being contained in a given set of CARs. The resulting "upload" will be associated with the memory space identified by the DID in the `with` field.
-
-#### Derivations
-
-`upload/add` can be derived from an `upload/*` or `*` capability with a matching `with` resource URI.
-
-#### Caveats
-
-When invoking `upload/add`, the `root` caveat must be set to the root CID of the data item.
-
-The `shards` array must contain at least one CID of a CAR file, which is expected to have been previously stored.
-
-Taken together, the CARs in the `shards` array should contain all the blocks in the DAG identified by the `root` CID.
-
-| field | value | required? | context |
-| ----------- | -------------------------------------------------------- | --------- | --------------------------------------------------------------- |
-| `can` | `upload/add` | β | The ability to add uploads to the index |
-| `with` | URI string, e.g. `did:key:123...` | β | The `did:` URI of the memory space to add to |
-| `nb.root` | data CID string, e.g. `bafy...` | β | The CID of the data item that was uploaded |
-| `nb.shards` | array of CID strings, e.g. `[ "bag123...", "bag234..."]` | β | The CIDs of CAR files containing the full DAG for the data item |
-
-
-### `upload/remove`
-
-> Remove an upload from a memory space.
-
-`upload/remove` can be invoked to remove the link between an uploaded data CID and the CARs containing the data.
-
-Note that this will not remove the stored CARs; you will need to use [`store/remove`](#storeremove) to remove the CARs once all uploads referencing those CARs have been removed.
-
-#### Derivations
-
-`upload/remove` can be derived from an `upload/*` or `*` capability with a matching `with` resource URI.
-
-#### Caveats
-
-The `with` resource URI must be set to the DID of the memory space to remove the upload from.
-
-The `root` caveat must contain the root CID of the data item to remove.
-
-| field | value | required? | context |
-| --------- | --------------------------------- | --------- | ------------------------------------------------------------ |
-| `can` | `upload/remove` | β | The ability to remove uploads from the index |
-| `with` | URI string, e.g. `did:key:123...` | β | The `did:` URI of the memory space to remove the upload from |
-| `nb.root` | data CID string, e.g. `bafy...` | β | The CID of the data item to remove |
-
-
-### `upload/list`
-
-> Obtain a list of uploaded data items.
-
-The `upload/list` capability can be invoked to request a list of metadata about uploads. See [services.md](./services.md#uploadlist) for details about the response.
-
-The `with` field of the invocation must be set to the DID of the memory space to be listed.
-
-#### Derivations
-
-`upload/list` can be derived from a `upload/*` or `*` capability with a matching `with` field.
-
-#### Caveats
-
-`cursor` can be set to start listing from an item in the middle of the list. Its value should be a `cursor` returned by a previous invocation of `upload/list`
-`size` can be set to change the number of items returned by an `upload/list` invocation
-`pre` can be set to `true` to return the page of results preceding `cursor` rather than the results after `cursor`. Defaults to `false`.
-
-| field | value | required? | context |
-| ----------- | ------------------------ | --------- | --------------------------------------------------------------- |
-| `nb.cursor` | string | β | A cursor returned by a previous invocation |
-| `nb.size` | integer | β | The maximum number of results to return |
-| `nb.pre` | boolean | β | If true, return the page of results preceding the cursor |
-
-## `voucher/` namespace
-
-TODO: more voucher docs when implementation details settle down a bit.
-
-### `voucher/claim`
-
-Request a voucher that can be redeemed to activate features and/or products for an account or agent DID.
-
-
-
-#### Caveats
-
-| field | value | required? | context |
-| ------------- | --------------------------------- | --------- | -------------------------------------------------------------------- |
-| `can` | `voucher/claim` | β | The ability to claim a voucher. |
-| `with` | DID string, e.g. `did:key:123...` | β | The DID of the service offering the product |
-| `nb.product` | URI string with `product:` scheme | β | A URI identifying the product |
-| `nb.identity` | string, e.g. `mailto:` | β | |
-| `nb.account` | DID string | β | The DID of the memory space or account that will receive the product |
-
-### `voucher/redeem`
-
-Redeeem a voucher to activate features / products for an account or agent DID.
-
-
\ No newline at end of file
diff --git a/spec/docs.css b/spec/docs.css
deleted file mode 100644
index 978385383..000000000
--- a/spec/docs.css
+++ /dev/null
@@ -1,12 +0,0 @@
-a[href*='_internal_.html'] + ul {
- display: none;
-}
-
-.tsd-kind-module > ul {
- display: none;
- overflow: hidden;
-}
-
-.tsd-kind-module.selected > ul {
- display: block;
-}
diff --git a/spec/registration.excalidraw.svg b/spec/registration.excalidraw.svg
deleted file mode 100644
index 8350affe2..000000000
--- a/spec/registration.excalidraw.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-
\ No newline at end of file
diff --git a/spec/sequences/participants.md b/spec/sequences/participants.md
deleted file mode 100644
index acaf76731..000000000
--- a/spec/sequences/participants.md
+++ /dev/null
@@ -1,31 +0,0 @@
-## Participants
-
-### Alice
-
-Normal human. Uses web browser to run recipe sharing app, and upload recipes and photos.
-
-### Biometric
-
-Manages non-extractable keypairs via touch / face ID or other factor.
-
-### Email Client
-
-We link the DID to your account by clicking a link sent to your email address.
-
-### AppUI
-
-A recipe app front-end, displays recipes and photos of recipes, allows creating and sharing new ones. Could be web or mobile app.
-
-### Keyring
-
-Signing engine using Alice's private keys stored on Alice's biometric device, managed via the keyring website origin, and accessed via web browser.
-
-> (Some Keyring stuff in here is w3up client... we should probably split them accurately to reflect the real thing.) --- @jchris
-
-### AppServer
-
-Traditonal web2 architecture. Maybe it's lambdas or an app server.
-
-### Storage
-
-The web3.storage service, w3up and w3access APIs.
\ No newline at end of file
diff --git a/spec/sequences/registration.md b/spec/sequences/registration.md
deleted file mode 100644
index b93984264..000000000
--- a/spec/sequences/registration.md
+++ /dev/null
@@ -1,81 +0,0 @@
-Regisitration is different depending on whether the app implements user-pays or app-pays storage payment models.
-
-# Payment models
-
-The two basic models are **user pays** and **app pays**. One is low-commitment for the developer, the other is invisible to the user. More nuanced hybrid models are also possible.
-
-## User pays (transparent to developer)
-
-In the default case, when a developer adds w3ui components to their application, the user is prompted to create a new (or link to an existing) account with web3.storage, where uploads are stored. When the user exceeds free plan usage, they will be prompted to provide a payment method.
-
-### Registration on first run (user pays)
-
-```mermaid
-sequenceDiagram
- participant Biometric
- participant Email Client
- participant AppUI
- participant Keyring
- participant AppServer
- participant Storage
-
- Note over AppServer, Storage: "The Cloud"
- Note over Biometric, Keyring: Alice's Device
- Note over Biometric: Biometric is optional
-
- AppUI ->> AppServer: Fetch web UI
- AppServer -->> AppUI: HTML content
- Note over AppUI: Running app
-
- AppUI ->> Keyring: Create DID
- Keyring ->> Biometric: New key please
- Note over Biometric: Scan face or thumb and generate private key.
- Biometric -->> Keyring: Here's a ref to it
- Note over Keyring: Collect email
- Keyring ->> Storage: Link this email to this DID
- Storage ->> Email Client: Send email with validation link
- Email Client -->> Storage: Alice clicks the validation link
- Storage -->> Keyring: Your DID is linked to your email, choose from these accounts or create a new one
- Note over Keyring: Choose account
- Keyring -->> AppUI: Your DID can upload now
- Note over AppUI: Store DID in session Should this be earlier?
-```
-
-> The word "account" in the "Choose account" box is confusing. Since your billing account (email-level grouping) can have very many of these (roughly one per app). And your keyring identity can have access to these namespaces without paying for them. So maybe we call them "buckets" or "containers" or "apps" or "namespaces". Maybe they are the same thing we give w3names to? --- @jchris
-
-## App pays (transparent to user)
-
-This assumes the App Server has already established a Storage account, and has access to private key signing capabilities (perhaps via an embedded web3.storage keyring). The servers's account will delegate access to user DIDs.
-
-### Registration on first run (app pays)
-
-
-```mermaid
-sequenceDiagram
- participant Biometric
- participant AppUI
- participant Keyring
- participant AppServer
-
- Note over AppServer: "The Cloud"
- Note over Biometric, Keyring: Alice's Device
- Note over Biometric: Biometric is optional
-
- AppUI ->> AppServer: Fetch web UI
- AppServer -->> AppUI: HTML content
- Note over AppUI: Running app
-
- AppUI ->> Keyring: Create DID
- Keyring ->> Biometric: New key please
- Note over Biometric: Scan face or thumb and generate private key.
- Biometric -->> Keyring: Here's a ref to it
- Keyring -->> AppUI: Here is an unlinked DID
- AppUI ->> AppServer: Please delegate storage access to this DID
- Note over AppServer: Validate user session & sign delegation
- AppServer -->> AppUI: Here's a delegation so your DID can upload now
- Note over AppUI: Store DID in session Should this be earlier?
-
-```
-
-> It might make sense to detail out the AppServer interactions with the AppServer Keyring. Currently the details on the app server delegation are elided.
-
diff --git a/spec/sequences/todo.md b/spec/sequences/todo.md
deleted file mode 100644
index b3716c9e9..000000000
--- a/spec/sequences/todo.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# Sequences to add coverage for
-
-* Flow for the app server registering the app account
-* Flow for the app server to list users uploads in app-pays mode
-* Session re-establishment flows for when delegations expire
\ No newline at end of file
diff --git a/spec/sequences/upload-and-list.md b/spec/sequences/upload-and-list.md
deleted file mode 100644
index ebd9edfde..000000000
--- a/spec/sequences/upload-and-list.md
+++ /dev/null
@@ -1,76 +0,0 @@
-Upload and list are basically the same regardless of which payment model is used.
-
-## Same flow whether app or user pays
-
-Once the AppUI has established a valid delegation for uploading, the upload logic proceeds the same no matter which payment model is in use.
-
-> In the below it starts to seem like maybe instead of Keyring we should be talking about w3up client... @jchris
-
-### Upload with valid delegation
-
-This will be the same both when the user pays, and in the case where the user's DID has a valid delegation allowing it to upload to the app's account.
-
-```mermaid
-sequenceDiagram
- participant Biometric
- participant AppUI
- participant Keyring
- participant AppServer
- participant Storage
-
- Note over AppServer, Storage: "The Cloud"
- Note over Biometric, Keyring: Alice's Device
- Note over Biometric: Biometric is optional
-
- AppUI ->> AppServer: Fetch web UI
- AppServer -->> AppUI: HTML content
- Note over AppUI: Running app
-
-AppUI ->> Keyring: Upload this file
-Keyring ->> Biometric: Sign this invocation
-Note over Biometric: Just sign, no scan.
-Biometric -->> Keyring: Here's the signature
-loop for chunk in file
- Keyring ->> Storage: Please run this upload invocation
- Storage -->> Keyring: OK, use these upload params
- Keyring ->> Storage: PUT the chunk
-end
-Keyring -->> AppUI: CID for uploaded file
-Note right of AppUI: Remainder is optional
-AppUI ->> AppServer: This CID is my recipe image
-Note over Storage: In the app pays model the AppServer can query Storage to list uploads
-AppServer -->> AppUI: ACK, I'll remember that
-
-```
-
-Note that in the server-pays model there will be other ways for the server to query user-saved data, so the user may not need to tell the server about their uploaded CID directly.
-
-
-### List uploads with valid delegation
-
-
-
-```mermaid
-sequenceDiagram
- participant Biometric
- participant AppUI
- participant Keyring
- participant AppServer
- participant Storage
-
- Note over AppServer, Storage: "The Cloud"
- Note over Biometric, Keyring: Alice's Device
- Note over Biometric: Biometric is optional
-
- AppUI ->> AppServer: Fetch web UI
- AppServer -->> AppUI: HTML content
- Note over AppUI: Running app
-
-AppUI ->> Keyring: List my uploads
-Keyring ->> Biometric: Sign this invocation
-Note over Biometric: Just sign, no scan.
-Biometric -->> Keyring: Here's the signature
-Keyring ->> Storage: Invoke this upload listing
-Storage -->> Keyring: Here's the list of uploads
-
-```
\ No newline at end of file
diff --git a/spec/services.md b/spec/services.md
deleted file mode 100644
index 4c4393d36..000000000
--- a/spec/services.md
+++ /dev/null
@@ -1,258 +0,0 @@
-# Service definitions
-
-This doc collects RPC interface definitions for the `w3-protocol` services.
-
-See [capabilities.md](./capabilities.md) for details about each of the capablities defined in the protocol. This doc builds upon those definitions and includes the result types and possible error cases for the implementation of each capability handler in our services. Third parties that want to provide an alternate implementation are encouraged to use compatible result and error types where possible.
-
-## What is a Service?
-
-We're using [ucanto](https://github.com/web3-storage/ucanto) to model services as a collection of related capabilities, which can be "invoked" by a user agent to perform some action and/or make a request.
-
-Capabilities are defined in terms of **abilities** and **resources**.
-
-The **ability** is a string identifying some "verb," or action that can be performed. Ability strings have a format of `namespace/action`, for example, `account/info`.
-
-A **resource** is something that can be acted upon, identified by a URI. In w3-protocol services, many of the resource URIs will be `did:` URIs that identify a user account or storage location.
-
-Capabilities may also contain **caveats**, which act like function parameters when used in an invocation.
-
-A `ucanto` service takes in a stream of invocations, which you can think of as serialized RPC requests that are encoded as UCANs and signed by the caller. An invocation must contain a proof that the capability being invoked has been delegated to the caller.
-
-A `ucanto` service uses the ability string to dispatch an invocation to the correct "capability provider" function, which executes some logic and (optionally) returns some result to the caller.
-
-See [capabilities.md](./capabilities.md) for more details about capabilities, including the optional and required caveats for each.
-
-## Error handling
-
-Most capability providers have error conditions that will result in a "failure" response instead of the expected success response.
-
-Ucanto's `Failure` type is a JavaScript `Error` subclass, from which custom error types are derived.
-
-When serialized to JSON, a `Failure` is represented as an object:
-
-```json
-{
- "error": true,
- "name": "TheNameOfTheError",
- "message": "A short message with details about what went wrong",
- "stack": "An optional stack trace."
-}
-```
-
-The table below lists `Failure` types that are [defined in ucanto](https://github.com/web3-storage/ucanto/blob/main/packages/validator/src/error.js). Many of the types below are returned by ucanto when validating invocations and delegations and are not specific to a particular capability or handler.
-
-The most common "capability specific" error is `MalformedCapability`, which is returned when an invocation is structurally correct and includes valid proofs, but the capability handler cannot process it, for example, because it has missing or invalid caveats.
-
-The `cause` field of a `MalformedCapabilty` object contains a `Failure` with details about the constraints that were violated.
-
-| name | description |
-| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
-| `EscalatedCapability` | A claimed capability exceeds the bounds of a delegation |
-| `InvalidClaim` | A claim is invalid for one or more reasons. Contains a `causes` field that contains the specific failures that occurred during validation. |
-| `InvalidSignature` | A signature is invalid |
-| `UnavailableProof` | A proof was referenced in a claim but could not be found by the validator. Applies only to proofs that are linked by CID, not those inlined into a UCAN. |
-| `InvalidAudience` | The audience of a delegation does not match the identity of the agent attempting to claim the capability |
-| `MalformedCapability` | An invocation lacks required caveats, or caveat values are invalid. Contains a `cause` field with a `Failure` describing the problem. |
-| `UnknownCapability` | An agent has tried to invoke a capability that the service is unaware of |
-| `Expired` | An agent is trying to claim a capability whose delegation has expired |
-| `NotValidBefore` | An agent is trying to claim a capability before the start of the delegation's validity period |
-
-
-## Accounts service
-
-### `account/info`
-
-Provides the [`account/info` capability](./capabilities.md#accountinfo).
-
-#### Invocation
-
-The `with` field of the invocation must contain the `did:` URI for the account to be identified.
-
-#### Response
-
-On success, the service returns an `Account` object with the following fields:
-
-| field | type | description |
-| ------------- | -------- | ----------------------------------------------------------- |
-| `did` | `string` | The DID of the account |
-| `agent` | `string` | The DID of the primary agent associated with the account |
-| `email` | `string` | The email registered to the account |
-| `product` | `string` | `product:` URI of product registered to the account, if any |
-| `updated_at` | `string` | ISO 8601 timestamp of last update to account record |
-| `inserted_at` | `string` | ISO 8601 timestamp of account record creation |
-
-#### Errors
-
-May fail with a `MalformedCapability` if the account does not exist.
-
-### `account/recover`
-
-### `account/recover-validation`
-
-
-## Storage service
-
-### `store/add`
-
-Provides the [`store/add` capability](./capabilities.md#storeadd), which can be invoked to store CAR files with the service.
-
-#### Invocation
-
-The `with` field of the invocation must contain the DID of a "memory space" that serves as the destination of the CAR. The invocation must contain proof that the caller posesses the `store/add` capability for the given space DID.
-
-The invocation must include a `link` caveat, whose value is the CID of the CAR to be stored. This implies that the caller must encode the CAR data and calculate the CID locally before invoking `store/add`.
-
-The invocation must also include a `size` caveat set to the size of the CAR in bytes.
-
-#### Response
-
-On success, the service will return an object containing status information, possibly including a signed URL for uploading CAR data.
-
-| field | type | description |
-| --------- | ------------------------ | ---------------------------------------------------------------------------------------------- |
-| `status` | `string` | One of `"upload"` or `"done"`, depending on whether the CAR is new to the service (see below) |
-| `with` | `string` | The DID of the memory space the CAR was added to |
-| `link` | `CID` | The CID of the added CAR file |
-| `url` | `string` | URL to send CAR data to. Only present if `status == "upload"` |
-| `headers` | `Record` | Headers to include in POST request when sending CAR data. Only present if `status == "upload"` |
-
-If the CID in the invocation's `link` caveat already exists on the service, e.g. because it was previously added by another agent, the `status` field in the response will be `"done"`, and the response will not include a URL for uploading.
-
-If the CAR has not been previously added, the `status` field will contain `"upload"`, and the `url` and `headers` fields will contain the information needed to send the CAR data to the storage backend.
-
-If the response contains `url` and `headers` fields, the client should issue an HTTP `POST` request to the URL and include the headers. The request body must be the CAR data, whose size and CID must match those in the invocation.
-
-#### Errors
-
-May fail with a `MalformedCapability` if no `link` caveat is provided.
-
-### `store/remove`
-
-Provides the [`store/remove` capability](./capabilities.md#storeremove), which removes the association between a CAR file and a memory space.
-
-#### Invocation
-
-The invocation's `with` field must be set to the DID of the memory space where the CAR is currently stored, and the caller must provide proof that they possess the `store/remove` capability for that space.
-
-The invocation's `link` caveat must be set to the CID of the CAR to be removed.
-
-#### Response
-
-On success, the service will echo back the CID of the removed CAR, as a string.
-
-#### Errors
-
-May fail with a `MalformedCapability` if no `link` caveat is provided.
-
-### `store/list`
-
-Provides the [`store/list` capability](./capabilities.md#storelist), which returns a list of stored CAR files for a given memory space.
-
-#### Invocation
-
-The invocation's `with` field must be set to the DID of the memory space to be listed, and the caller must provide proof that they posess the `store/list` capability for that space.
-
-Note that caveats for pagination will be added in the near future.
-
-#### Response
-
-On success, returns an object whose `results` field contains an array of `StoreItem` metadata objects for each stored CAR.
-
-A `StoreItem` has the following fields:
-
-| field | type | description |
-| ---------------- | ---------------- | -------------------------------------------------------------- |
-| `uploaderDID` | `string` | The DID of the agent who uploaded the CAR |
-| `payloadCID` | `string` (`CID`) | The CID of the CAR |
-| `applicationDID` | `string` | Reserved for future use |
-| `origin` | `string` (`CID`) | Link from this CAR to another shard of the same DAG (optional) |
-| `proof` | `string` | Encoded UCAN of proof included with upload invocation |
-| `size` | `number` | Size of CAR data in bytes |
-| `uploadedAt` | `string` | ISO 8601 timestamp of upload |
-
-The full response object returned by `store/list` currently looks like this, although there may be changes when pagination is fully implemented. Currently, the service always returns all results in a single "page".
-
-| field | type | description |
-| ---------- | ------------- | --------------------------------------------------------- |
-| `count` | `number` | The total number of CARs in the memory space |
-| `pages` | `number` | The number of pages available in the listing |
-| `page` | `number` | The index of the current page of results |
-| `pageSize` | `number` | The max number of results in each page |
-| `results` | `StoreItem[]` | An array of `StoreItem`s (see above) for the current page |
-
-## Uploads service
-
-The uploads service provides capabilities that link "data CIDs" to "CAR CIDs". A data CID is the root of some user-provided DAG, e.g. a UnixFs directory tree or a dag-cbor object. An "upload" is an association between a data CID and one or more CARs that contain the blocks of the DAG.
-
-There is a many-to-many relationship between data CIDs and CAR CIDs. A single CAR can contain multiple data CIDs, and the DAG for a given data CID may be "sharded" across multiple CARs.
-
-### `upload/add`
-
-Provides the [`upload/add` capability](./capabilities.md#uploadadd), which adds an association between a root data CID and the set of CAR "shards" containing the data.
-
-#### Invocation
-
-The `with` field of the invocation must contain the DID of a "memory space," and the caller must provide proof that they possess the `upload/add` capability for that space.
-
-The `root` caveat must be set to the root CID string of the data item supplied by the user.
-
-The `shards` caveat must be set to an array of CID strings that identify the CARs containing the data blocks referenced by the `root` data CID. These CARs are expected to have been previously stored with [`store/add`](#storeadd).
-
-#### Response
-
-The current implementation returns `null` on success, but this may be changed in the future to return an object describing upload.
-
-#### Errors
-
-May fail with a `MalformedCapability` if no `root` CID caveat is provided, or if the `shards` caveat is missing or contains an empty array.
-
-### `upload/remove`
-
-Provides the [`upload/remove` capability](./capabilities.md#uploadremove), which removes an upload from a given "memory space".
-
-#### Invocation
-
-The `with` field of the invocation must contain the DID of a "memory space," and the caller must provide proof that they possess the `upload/remove` capability for that space.
-
-The `root` caveat must be set to the root "data CID" to be removed.
-
-#### Response
-
-The service currently returns no value on success.
-
-#### Errors
-
-May fail with a `MalformedCapability` if no `root` CID caveat was provided.
-
-### `upload/list`
-
-Provides the [`upload/list` capability](./capabilities.md#uploadlist). Upon invocation, returns a list of metadata objects describing the uploads contained in a memory space.
-
-#### Invocation
-
-The `with` field of the invocation must contain the DID of a "memory space," and the caller must provide proof that they possess the `upload/list` capability for that space.
-
-#### Response
-
-On success, returns an object whose `results` field contains an array of `UploadItem` metadata objects for each upload.
-
-An `UploadItem` has the following fields:
-
-| field | type | description |
-| ------------- | ---------------- | --------------------------------------------------------------------------------- |
-| `uploaderDID` | `string` | The DID of the agent who uploaded the CAR |
-| `dataCID` | `string` (`CID`) | The root CID of the stored data item |
-| `carCID` | `string` | The CID of a CAR associated with this upload. See below for notes about sharding. |
-| `uploadedAt` | `string` | ISO 8601 timestamp of upload |
-
-Note that each `UploadItem` contains a single `carCID`. For uploads that span multiple CARs, the response will contain multiple `UploadItem`s with the same `dataCID`, but with different `carCID`s, which should be collected on the client to get the full set of CAR CIDs for a "sharded" upload.
-
-The full response object returned by `upload/list` currently looks like this, although there may be changes when pagination is fully implemented. Currently, the service always returns all results in a single "page".
-
-| field | type | description |
-| ---------- | -------------- | ---------------------------------------------------------- |
-| `count` | `number` | The total number of CARs in the memory space |
-| `pages` | `number` | The number of pages available in the listing |
-| `page` | `number` | The index of the current page of results |
-| `pageSize` | `number` | The max number of results in each page |
-| `results` | `UploadItem[]` | An array of `UploadItem`s (see above) for the current page |
\ No newline at end of file
diff --git a/spec/system.excalidraw.svg b/spec/system.excalidraw.svg
deleted file mode 100644
index dcb103617..000000000
--- a/spec/system.excalidraw.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-
\ No newline at end of file