Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add doc comments to the capabilities #159

Merged
merged 9 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions packages/access-api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@
"license": "(Apache-2.0 OR MIT)",
"dependencies": {
"@ipld/dag-ucan": "^2.0.1",
"@ucanto/client": "^3.0.1",
"@ucanto/core": "^3.0.1",
"@ucanto/interface": "^3.0.0",
"@ucanto/principal": "^3.0.0",
"@ucanto/server": "^3.0.1",
"@ucanto/transport": "^3.0.1",
"@ucanto/validator": "^3.0.1",
"@ucanto/client": "^3.0.2",
"@ucanto/core": "^3.0.2",
"@ucanto/interface": "^3.0.1",
"@ucanto/principal": "^3.0.1",
"@ucanto/server": "^3.0.4",
"@ucanto/transport": "^3.0.2",
"@ucanto/validator": "^3.0.4",
"@web3-storage/access": "workspace:^",
"@web3-storage/worker-utils": "0.4.3-dev",
"multiformats": "^10.0.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/access-api/test/helpers/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export async function send(ucan, mf) {

/**
* @param {Types.Signer} issuer
* @param {Types.Principal} service
* @param {Types.Principal<"key">} service
* @param {Types.ConnectionView<import('@web3-storage/access/types').Service>} conn
* @param {string} email
*/
Expand Down
14 changes: 7 additions & 7 deletions packages/access/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@
"@ipld/dag-ucan": "^2.0.1",
"@noble/ed25519": "^1.7.1",
"@types/ws": "^8.5.3",
"@ucanto/client": "^3.0.1",
"@ucanto/core": "^3.0.1",
"@ucanto/interface": "^3.0.0",
"@ucanto/principal": "^3.0.0",
"@ucanto/server": "^3.0.1",
"@ucanto/transport": "^3.0.1",
"@ucanto/validator": "^3.0.1",
"@ucanto/client": "^3.0.2",
"@ucanto/core": "^3.0.2",
"@ucanto/interface": "^3.0.1",
"@ucanto/principal": "^3.0.1",
"@ucanto/server": "^3.0.4",
"@ucanto/transport": "^3.0.2",
"@ucanto/validator": "^3.0.4",
"@web-std/fetch": "^4.1.0",
"bigint-mod-arith": "^3.1.2",
"conf": "^10.1.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/access/src/agent.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export async function connection(principal, _fetch, url) {
* Agent
*/
export class Agent {
/** @type {Ucanto.Principal|undefined} */
/** @type {Ucanto.Principal<"key">|undefined} */
#service

/** @type {typeof fetch} */
Expand Down
80 changes: 73 additions & 7 deletions packages/access/src/capabilities/store.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,27 @@
/* eslint-disable jsdoc/require-param */
import { capability, Failure, Link, URI, Schema } from '@ucanto/validator'
import { equalLink, equalWith } from './utils.js'
import { any } from './any.js'

/**
* all the `store/*` capabilities which can also be derived
* from any capability.
* Capability can only be delegated (but not invoked) allowing audience to
* derived any `store/` prefixed capability for the (memory) space identified
* by did:key in the `with` field.
*/
export const store = any.derive({
to: capability({
can: 'store/*',
/**
* did:key identifier of the (memory) space where CAR is intended to
* be stored.
*/
with: URI.match({ protocol: 'did:' }),
derives: equalWith,
}),
/**
* `store/*` can be derived from the `*` capability as long as `with` field
* is the same.
*/
derives: equalWith,
})

Expand All @@ -23,17 +33,42 @@ export const store = any.derive({
const base = any.or(store)

/**
* `store/add` can be derived from the `store/*` capability
* as long as with fields match.
* `store/add` capability allows agent to store a CAR file into a (memory) space
* identified by did:key in the `with` field. Agent must precompute CAR locally
* and provide it's CID and size using `nb.link` and `nb.size` fields, allowing
* a service to provision a write location for the agent to PUT or POST desired
* CAR into.
*/
export const add = base.derive({
to: capability({
can: 'store/add',
/**
* did:key identifier of the (memory) space where CAR is intended to
* be stored.
*/
with: URI.match({ protocol: 'did:' }),
nb: {
link: Link.optional(),
/**
* CID of the CAR file to be stored. Service will provision write target
* for this exact CAR file for agent to PUT or POST it. Attempt to write
* any other content will fail.
*/
link: Link,
/**
* Size of the CAR file to be stored. Service will provision write target
* for this exact size. Attempt to write a larger CAR file will fail.
*/
size: Schema.integer(),
/**
* Agent may optionally provide a link to a related CAR file using `origin`
* field. This is useful when storing large DAGs, agent could shard it
* across multiple CAR files and then link each shard with a previous one.
*
* Providing this relation tells service that given CAR is shard of the
* larger DAG as opposed to it being intentionally partial DAG. When DAG is
* not sharded, there will be only one `store/add` with `origin` left out.
*/
origin: Link.optional(),
Gozala marked this conversation as resolved.
Show resolved Hide resolved
size: Schema.integer().optional(),
},
derives: (claim, from) => {
const result = equalLink(claim, from)
Expand All @@ -50,24 +85,51 @@ export const add = base.derive({
}
},
}),
/**
* `store/add` can be derived from the `store/*` & `*` capability
* as long as the `with` fields match.
*/
derives: equalWith,
})

/**
* Capability can be used to remove the stored CAR file from the (memory)
* space identified by `with` field.
*/
export const remove = base.derive({
to: capability({
can: 'store/remove',
/**
* did:key identifier of the (memory) space where CAR is intended to
* be stored.
*/
with: URI.match({ protocol: 'did:' }),
nb: {
link: Link.optional(),
/**
* CID of the CAR file to be removed from the store.
*/
link: Link,
},
derives: equalLink,
}),
/**
* `store/remove` can be derived from the `store/*` & `*` capability
* as long as the `with` fields match.
*/
derives: equalWith,
})

/**
* Capability can be invoked to request a list of stored CAR files in the
* (memory) space identified by `with` field.
*/
export const list = base.derive({
to: capability({
can: 'store/list',
/**
* did:key identifier of the (memory) space where CAR is intended to
* be stored.
*/
with: URI.match({ protocol: 'did:' }),
derives: (claimed, delegated) => {
if (claimed.with !== delegated.with) {
Expand All @@ -78,6 +140,10 @@ export const list = base.derive({
return true
},
}),
/**
* `store/list` can be derived from the `store/*` & `*` capability
* as long as the `with` fields match.
*/
derives: equalWith,
})

Expand Down
79 changes: 71 additions & 8 deletions packages/access/src/capabilities/upload.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
import { capability, Link, URI } from '@ucanto/validator'
import { codec } from '@ucanto/transport/car'
import { codec as CAR } from '@ucanto/transport/car'
import { equalWith, fail, equal } from './utils.js'
import { any } from './any.js'

/**
* All the `upload/*` capabilities which can also be derived
* from `any` (a.k.a `*`) capability.
* Capability can only be delegated (but not invoked) allowing audience to
* derived any `upload/` prefixed capability for the (memory) space identified
* by did:key in the `with` field.
*/
export const upload = any.derive({
to: capability({
can: 'upload/*',
/**
* did:key identifier of the (memory) space where upload is add to the
* upload list.
*/
with: URI.match({ protocol: 'did:' }),
derives: equalWith,
}),
/**
* `upload/*` can be derived from the `*` capability as long as `with` field
* is the same.
*/
derives: equalWith,
})

Expand All @@ -23,18 +32,45 @@ export const upload = any.derive({
// `upload/*`.
const base = any.or(upload)

const CARLink = Link.match({ code: codec.code, version: 1 })
/**
* Schema representing a link (a.k.a CID) to a CAR file. Enforces CAR codec code and CID v1.
*/
const CARLink = Link.match({ code: CAR.code, version: 1 })

/**
* `upload/add` can be derived from the `upload/*` capability
* as long as with fields match.
* Capability allows an agent to add an arbitrary DAG (root) to the upload list
* of the specified (memory) space (identified by did:key in the `with` field).
* It is recommended to provide an optional list of shard links that contain
* fragments of this DAG, as it allows system to optimize block discovery, it is
* also a way to communicate DAG partiality - this upload contains partial DAG
* identified by the given `root`.
*
* Usually when agent wants to upload a DAG it will encode it as a one or more
* CAR files (shards) and invoke `store/add` capability for each one. Once all
* shards are stored it will invoke `upload/add` capability (providing link to
* a DAG root and all the shards) to add it the upload list.
*
* That said `upload/add` could be invoked without invoking `store/add`s e.g.
* because another (memory) space may already have those CARs.
*
* Note: If DAG with the given root is already in the upload list, invocation
* will simply update `shards` to be a union of existing and new shards.
*/
export const add = base.derive({
to: capability({
can: 'upload/add',
/**
* did:key identifier of the (memory) space where uploaded is added.
*/
with: URI.match({ protocol: 'did:' }),
nb: {
root: Link.optional(),
/**
* Root CID of the DAG to be added to the upload list.
*/
root: Link,
/**
* CIDs to the CAR files that contain blocks of the DAG.
*/
shards: CARLink.array().optional(),
},
derives: (self, from) => {
Expand All @@ -46,15 +82,30 @@ export const add = base.derive({
)
},
}),
/**
* `upload/add` can be derived from the `upload/*` & `*` capability
* as long as `with` fields match.
*/
derives: equalWith,
})

/**
* Capability removes an upload (identified by it's root CID) from the upload
* list. Please note that removing an upload does not delete corresponding shards
* from the store, however that could be done via `store/remove` invocations.
*/
export const remove = base.derive({
to: capability({
can: 'upload/remove',
/**
* did:key identifier of the (memory) space where uploaded is removed from.
*/
with: URI.match({ protocol: 'did:' }),
nb: {
root: Link.optional(),
/**
* Root CID of the DAG to be removed from the upload list.
*/
root: Link,
},
derives: (self, from) => {
return (
Expand All @@ -64,13 +115,25 @@ export const remove = base.derive({
)
},
}),
/**
* `upload/remove` can be derived from the `upload/*` & `*` capability
* as long as `with` fields match.
*/
derives: equalWith,
})

/**
* Capability can be invoked to request a list of uploads in the (memory) space
* identified by the `with` field.
*/
export const list = base.derive({
to: capability({
can: 'upload/list',
with: URI.match({ protocol: 'did:' }),
}),
/**
* `upload/list` can be derived from the `upload/*` & `*` capability
* as long as with fields match.
*/
derives: equalWith,
})
Loading