diff --git a/packages/access-api/package.json b/packages/access-api/package.json index 5bdd516fd..03d6a652a 100644 --- a/packages/access-api/package.json +++ b/packages/access-api/package.json @@ -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", diff --git a/packages/access-api/test/helpers/utils.js b/packages/access-api/test/helpers/utils.js index fbcd102f2..d2af8a1c7 100644 --- a/packages/access-api/test/helpers/utils.js +++ b/packages/access-api/test/helpers/utils.js @@ -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} conn * @param {string} email */ diff --git a/packages/access/package.json b/packages/access/package.json index c9ef88004..b74712857 100644 --- a/packages/access/package.json +++ b/packages/access/package.json @@ -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", diff --git a/packages/access/src/agent.js b/packages/access/src/agent.js index ccd94b30a..ed359eb57 100644 --- a/packages/access/src/agent.js +++ b/packages/access/src/agent.js @@ -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} */ diff --git a/packages/access/src/capabilities/store.js b/packages/access/src/capabilities/store.js index 0375072d8..c146d544e 100644 --- a/packages/access/src/capabilities/store.js +++ b/packages/access/src/capabilities/store.js @@ -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, }) @@ -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(), - size: Schema.integer().optional(), }, derives: (claim, from) => { const result = equalLink(claim, from) @@ -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) { @@ -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, }) diff --git a/packages/access/src/capabilities/upload.js b/packages/access/src/capabilities/upload.js index e5a2ae1df..cb033c9d2 100644 --- a/packages/access/src/capabilities/upload.js +++ b/packages/access/src/capabilities/upload.js @@ -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, }) @@ -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) => { @@ -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 ( @@ -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, }) diff --git a/packages/access/src/capabilities/voucher.js b/packages/access/src/capabilities/voucher.js index 50e172c7f..26d668cd9 100644 --- a/packages/access/src/capabilities/voucher.js +++ b/packages/access/src/capabilities/voucher.js @@ -1,10 +1,31 @@ -import { capability, URI } from '@ucanto/validator' -// @ts-ignore -// eslint-disable-next-line no-unused-vars -import * as Types from '@ucanto/interface' -import { canDelegateURI, equalWith, fail } from './utils.js' +import { capability, URI, DID } from '@ucanto/validator' +import { equalWith, equal, fail } from './utils.js' import { any } from './any.js' +/** + * Products are identified by the CID of the DAG that describes them. + */ +export const Product = URI.uri() + +/** + * Verifiable identity to whom voucher is issued. Currently it is a `mailto:` + * URL. + */ +export const Identity = URI.match({ protocol: 'mailto:' }) + +/** + * Services are identified using did:key identifier. + */ +export const Service = DID.match({ method: 'key' }) + +/** + * Capability can only be delegated (but not invoked) allowing audience to + * derived any `voucher/` prefixed capability for the (memory) space identified + * by did:key in the `with` field. + * + * Currently DID in the `with` field will always be web3.storage DID since we + * do not support other types of vouchers yet. + */ export const voucher = any.derive({ to: capability({ can: 'voucher/*', @@ -16,25 +37,47 @@ export const voucher = any.derive({ const base = any.or(voucher) +/** + * Capability can be invoked by an agent to claim a voucher for a specific + * user identifier (currently email address). + * + * The agent MAY issue claim with own DID or a DID it is delegate of. If `with` + * is different from `iss`, it is implied that the voucher is claimed for the + * DID in the `with` field. If `with` is same as `iss` it is implies that + * voucher is claimed for an unspecified `did`. + */ export const claim = base.derive({ to: capability({ can: 'voucher/claim', with: URI.match({ protocol: 'did:' }), nb: { - product: URI.match({ protocol: 'product:' }), - identity: URI.match({ protocol: 'mailto:' }), - service: URI.match({ protocol: 'did:' }), + /** + * URI of the product agent is requesting a voucher of. + */ + product: Product, + /** + * Verifiable identity on who's behalf behalf claim is made. + */ + identity: Identity, + /** + * Optional service DID who's voucher is been requested. + */ + service: Service.optional(), }, derives: (child, parent) => { return ( fail(equalWith(child, parent)) || - fail(canDelegateURI(child.nb.identity, parent.nb.identity)) || - fail(canDelegateURI(child.nb.product, parent.nb.product)) || - fail(canDelegateURI(child.nb.service, parent.nb.service)) || + fail(equal(child.nb.product, parent.nb.product, 'product')) || + fail(equal(child.nb.identity, parent.nb.identity, 'identity')) || + fail(equal(child.nb.service, parent.nb.service, 'service')) || true ) }, }), + /** + * `voucher/claim` can be derived from the `voucher/*` & `*` capability + * as long as the `with` fields match. + */ derives: equalWith, }) @@ -43,19 +86,36 @@ export const redeem = voucher.derive({ can: 'voucher/redeem', with: URI.match({ protocol: 'did:' }), nb: { - product: URI.match({ protocol: 'product:' }), - identity: URI.match({ protocol: 'mailto:' }), + /** + * Link of the product voucher is for. Must be the same as `nb.product` + * of `voucher/claim` that requested this. + */ + product: Product, + /** + * Verifiable identity to whom voucher is issued. It is a `mailto:` URL + * where this delegation is typically sent. + */ + identity: Identity, + /** + * Space identifier where voucher can be redeemed. When service delegates + * `voucher/redeem` to the user agent it may omit this field to allow + * account to choose account. + */ account: URI.match({ protocol: 'did:' }), }, derives: (child, parent) => { return ( fail(equalWith(child, parent)) || - fail(canDelegateURI(child.nb.identity, parent.nb.identity)) || - fail(canDelegateURI(child.nb.product, parent.nb.product)) || - fail(canDelegateURI(child.nb.account, parent.nb.account)) || + fail(equal(child.nb.product, parent.nb.product, 'product')) || + fail(equal(child.nb.identity, parent.nb.identity, 'identity')) || + fail(equal(child.nb.account, parent.nb.account, 'account')) || true ) }, }), + /** + * `voucher/redeem` can be derived from the `voucher/*` & `*` capability + * as long as the `with` fields match. + */ derives: equalWith, }) diff --git a/packages/access/test/capabilities/store.test.js b/packages/access/test/capabilities/store.test.js index d25358e19..2f45cbc4c 100644 --- a/packages/access/test/capabilities/store.test.js +++ b/packages/access/test/capabilities/store.test.js @@ -4,6 +4,8 @@ import { access } from '@ucanto/validator' import { Verifier } from '@ucanto/principal' import { delegate, parseLink } from '@ucanto/core' import * as Store from '../../src/capabilities/store.js' +import * as Capability from '../../src/capabilities/any.js' + import { alice, service as w3, @@ -12,29 +14,22 @@ import { } from '../helpers/fixtures.js' import { createCarCid } from '../helpers/utils.js' -describe('store capabilities', function () { - const any = delegate({ +const any = async () => + Capability.any.delegate({ issuer: account, audience: alice, - capabilities: [ - { - can: '*', - with: account.did(), - }, - ], + with: account.did(), }) - const store = delegate({ +const store = async () => + Store.store.delegate({ issuer: account, audience: alice, - capabilities: [ - { - can: 'store/*', - with: account.did(), - }, - ], + with: account.did(), + proofs: [await any()], }) +describe('store capabilities', function () { it('store/add can be derived from *', async () => { const add = Store.add.invoke({ issuer: alice, @@ -42,16 +37,14 @@ describe('store capabilities', function () { with: account.did(), nb: { link: parseLink('bafkqaaa'), + size: 0, }, - proofs: [await any], + proofs: [await any()], }) const result = await access(await add.delegate(), { capability: Store.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -62,6 +55,7 @@ describe('store capabilities', function () { assert.equal(result.capability.can, 'store/add') assert.deepEqual(result.capability.nb, { link: parseLink('bafkqaaa'), + size: 0, }) }) @@ -72,16 +66,14 @@ describe('store capabilities', function () { with: account.did(), nb: { link: parseLink('bafkqaaa'), + size: 0, }, - proofs: [await store], + proofs: [await store()], }) const result = await access(await add.delegate(), { capability: Store.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -92,31 +84,16 @@ describe('store capabilities', function () { assert.equal(result.capability.can, 'store/add') assert.deepEqual(result.capability.nb, { link: parseLink('bafkqaaa'), + size: 0, }) }) it('store/add can be derived from store/* derived from *', async () => { - const any = await delegate({ - issuer: account, - audience: alice, - capabilities: [ - { - can: '*', - with: account.did(), - }, - ], - }) - - const store = await delegate({ + const store = await Store.store.delegate({ issuer: alice, audience: bob, - capabilities: [ - { - can: 'store/*', - with: account.did(), - }, - ], - proofs: [any], + with: account.did(), + proofs: [await any()], }) const add = Store.add.invoke({ @@ -125,6 +102,7 @@ describe('store capabilities', function () { with: account.did(), nb: { link: parseLink('bafkqaaa'), + size: 0, }, proofs: [store], }) @@ -132,9 +110,6 @@ describe('store capabilities', function () { const result = await access(await add.delegate(), { capability: Store.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -145,21 +120,20 @@ describe('store capabilities', function () { assert.equal(result.capability.can, 'store/add') assert.deepEqual(result.capability.nb, { link: parseLink('bafkqaaa'), + size: 0, }) }) it('store/add sholud fail when escalating size constraint', async () => { - const delegation = await Store.add - .invoke({ - issuer: alice, - audience: bob, - with: account.did(), - nb: { - size: 1024, - }, - proofs: [await any], - }) - .delegate() + const delegation = await Store.add.delegate({ + issuer: alice, + audience: bob, + with: account.did(), + nb: { + size: 1024, + }, + proofs: [await any()], + }) { const add = Store.add.invoke({ @@ -176,9 +150,6 @@ describe('store capabilities', function () { const result = await access(await add.delegate(), { capability: Store.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -208,9 +179,6 @@ describe('store capabilities', function () { const result = await access(await add.delegate(), { capability: Store.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) @@ -222,13 +190,14 @@ describe('store capabilities', function () { for (const size of fixtures) { const json = JSON.stringify(size) it(`store/add size must be an int not ${json}`, async () => { - const proofs = [await any] + const proofs = [await any()] assert.throws(() => { Store.add.invoke({ issuer: alice, audience: w3, with: account.did(), nb: { + link: parseLink('bafkqaaa'), // @ts-expect-error size, }, @@ -251,16 +220,13 @@ describe('store capabilities', function () { }, }, ], - proofs: [await any], + proofs: [await any()], }) // @ts-expect-error - size type doesnt not match because we are testing fails const result = await access(add, { capability: Store.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) @@ -269,13 +235,14 @@ describe('store capabilities', function () { } it('store/add size must be an int', async () => { - const proofs = [await any] + const proofs = [await any()] assert.throws(() => { Store.add.invoke({ issuer: alice, audience: w3, with: account.did(), nb: { + link: parseLink('bafkqaaa'), size: 1024.2, }, proofs, diff --git a/packages/access/test/capabilities/upload.test.js b/packages/access/test/capabilities/upload.test.js index e851e7c33..31422a8a1 100644 --- a/packages/access/test/capabilities/upload.test.js +++ b/packages/access/test/capabilities/upload.test.js @@ -48,9 +48,6 @@ describe('upload capabilities', function () { const result = await access(await add.delegate(), { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -86,9 +83,6 @@ describe('upload capabilities', function () { const result = await access(await add.delegate(), { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -140,9 +134,6 @@ describe('upload capabilities', function () { const result = await access(add, { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) assert(String(result).includes('Expected link to be CID with 0x202 codec')) @@ -165,9 +156,6 @@ describe('upload capabilities', function () { const result = await access(await add.delegate(), { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -216,9 +204,6 @@ describe('upload capabilities', function () { const result = await access(add, { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) @@ -230,15 +215,12 @@ describe('upload capabilities', function () { }) it('upload/add should work when escalating root when caveats not imposed on proof', async () => { - const delegation = Upload.add - .invoke({ - issuer: alice, - audience: bob, - with: account.did(), - nb: {}, - proofs: [await any], - }) - .delegate() + const delegation = await Upload.add.delegate({ + issuer: alice, + audience: bob, + with: account.did(), + proofs: [await any], + }) const root = await createCborCid('root') @@ -255,9 +237,6 @@ describe('upload capabilities', function () { const result = await access(await add.delegate(), { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -298,9 +277,6 @@ describe('upload capabilities', function () { const result = await access(await add.delegate(), { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) @@ -313,17 +289,15 @@ describe('upload capabilities', function () { it('upload/add should fail when escalating shards', async () => { const shard = await createCarCid('shard') - const delegation = Upload.add - .invoke({ - issuer: alice, - audience: bob, - with: account.did(), - nb: { - shards: [shard], - }, - proofs: [await any], - }) - .delegate() + const delegation = await Upload.add.delegate({ + issuer: alice, + audience: bob, + with: account.did(), + nb: { + shards: [shard], + }, + proofs: [await any], + }) const add = Upload.add.invoke({ issuer: bob, @@ -338,9 +312,6 @@ describe('upload capabilities', function () { const result = await access(await add.delegate(), { capability: Upload.add, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) @@ -362,9 +333,6 @@ describe('upload capabilities', function () { const result = await access(await list.delegate(), { capability: Upload.list, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -394,9 +362,6 @@ describe('upload capabilities', function () { const result = await access(await list.delegate(), { capability: Upload.list, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -426,9 +391,6 @@ describe('upload capabilities', function () { const result = await access(await list.delegate(), { capability: Upload.list, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -469,9 +431,6 @@ describe('upload capabilities', function () { const result = await access(list, { capability: Upload.list, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) assert( @@ -495,9 +454,6 @@ describe('upload capabilities', function () { const result = await access(await remove.delegate(), { capability: Upload.remove, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -532,9 +488,6 @@ describe('upload capabilities', function () { const result = await access(await remove.delegate(), { capability: Upload.remove, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -572,9 +525,6 @@ describe('upload capabilities', function () { const result = await access(await remove.delegate(), { capability: Upload.remove, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { @@ -619,9 +569,6 @@ describe('upload capabilities', function () { const result = await access(remove, { capability: Upload.remove, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) assert( @@ -659,9 +606,6 @@ describe('upload capabilities', function () { const result = await access(await remove.delegate(), { capability: Upload.remove, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) assert.equal(result.error, true) diff --git a/packages/access/test/capabilities/voucher.test.js b/packages/access/test/capabilities/voucher.test.js index 056b4b1dc..2e55dbc26 100644 --- a/packages/access/test/capabilities/voucher.test.js +++ b/packages/access/test/capabilities/voucher.test.js @@ -34,9 +34,6 @@ describe('voucher capabilities', function () { const result = await access(await claim.delegate(), { capability: Voucher.claim, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (!result.error) { assert.deepEqual(result.audience.did(), service.did()) @@ -60,27 +57,22 @@ describe('voucher capabilities', function () { service: service.did(), }, proofs: [ - await Voucher.claim - .invoke({ - issuer: alice, - audience: bob, - with: alice.did(), - nb: { - identity: 'mailto:alice@email.com', - product: 'product:free', - service: service.did(), - }, - }) - .delegate(), + await Voucher.claim.delegate({ + issuer: alice, + audience: bob, + with: alice.did(), + nb: { + identity: 'mailto:alice@email.com', + product: 'product:free', + service: service.did(), + }, + }), ], }) const result = await access(await claim.delegate(), { capability: Voucher.claim, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (!result.error) { @@ -107,27 +99,22 @@ describe('voucher capabilities', function () { service: service.did(), }, proofs: [ - await Voucher.claim - .invoke({ - issuer: alice, - audience: bob, - with: alice.did(), - nb: { - identity: 'mailto:alice@email.com', - product: 'product:free', - service: service.did(), - }, - }) - .delegate(), + await Voucher.claim.delegate({ + issuer: alice, + audience: bob, + with: alice.did(), + nb: { + identity: 'mailto:alice@email.com', + product: 'product:free', + service: service.did(), + }, + }), ], }) const result = await access(await claim.delegate(), { capability: Voucher.claim, principal: Verifier, - canIssue: (claim, issuer) => { - return claim.with === issuer - }, }) if (result.error) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index defdcdc0c..84966979c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -26,13 +26,13 @@ importers: '@types/mocha': ^10.0.0 '@types/node': ^18.11.7 '@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 assert: ^2.0.0 bigint-mod-arith: ^3.1.2 @@ -65,13 +65,13 @@ importers: '@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.2.0 @@ -117,13 +117,13 @@ importers: '@types/git-rev-sync': ^2.0.0 '@types/node': ^18.11.7 '@types/qrcode': ^1.5.0 - '@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 assert: ^2.0.0 @@ -152,13 +152,13 @@ importers: wrangler: ^2.1.13 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': link:../access '@web3-storage/worker-utils': 0.4.3-dev multiformats: 10.0.2 @@ -259,24 +259,6 @@ importers: typescript: 4.8.4 wrangler: 2.1.15 - packages/upload-client: - specifiers: - '@types/assert': ^1.5.6 - '@types/mocha': ^10.0.0 - assert: ^2.0.0 - hd-scripts: ^3.0.2 - mocha: ^10.1.0 - playwright-test: ^8.1.1 - typescript: ^4.8.4 - devDependencies: - '@types/assert': 1.5.6 - '@types/mocha': 10.0.0 - assert: 2.0.0 - hd-scripts: 3.0.2 - mocha: 10.1.0 - playwright-test: 8.1.1 - typescript: 4.8.4 - packages/store: specifiers: '@types/chai': ^4.3.0 @@ -303,9 +285,9 @@ importers: '@ucanto/core': 3.0.1 '@ucanto/interface': 3.0.0 '@ucanto/principal': 3.0.0 - '@ucanto/server': 3.0.1 + '@ucanto/server': 3.0.4 '@ucanto/transport': 3.0.1 - '@ucanto/validator': 3.0.1 + '@ucanto/validator': 3.0.4 '@web-std/fetch': 4.1.0 '@web3-storage/sigv4': 1.0.2 multiformats: 10.0.2 @@ -320,6 +302,24 @@ importers: playwright-test: 8.1.1 typescript: 4.8.4 + packages/upload-client: + specifiers: + '@types/assert': ^1.5.6 + '@types/mocha': ^10.0.0 + assert: ^2.0.0 + hd-scripts: ^3.0.2 + mocha: ^10.1.0 + playwright-test: ^8.1.1 + typescript: ^4.8.4 + devDependencies: + '@types/assert': 1.5.6 + '@types/mocha': 10.0.0 + assert: 2.0.0 + hd-scripts: 3.0.2 + mocha: 10.1.0 + playwright-test: 8.1.1 + typescript: 4.8.4 + packages/wallet: specifiers: '@types/node': ^18.11.7 @@ -1425,7 +1425,14 @@ packages: /@ucanto/client/3.0.1: resolution: {integrity: sha512-rK0M3kqLHlvLTp6P9jyqjSOdzGbulawxzfFOh0cV4D6FLLjpHwNq5NpXZ7n6AbQ7H1EQeWla/gNgLKVGWXKrMQ==} dependencies: - '@ucanto/interface': 3.0.0 + '@ucanto/interface': 3.0.1 + multiformats: 10.0.2 + dev: false + + /@ucanto/client/3.0.2: + resolution: {integrity: sha512-viYv/fLPvH/POFIfVoIaK4B8KSYIBLNZeVFCdnhSbS4/m6t3h4G0Z7GMjNyP1mZG/CGjAOmHxeNvMUr0sNCyVQ==} + dependencies: + '@ucanto/interface': 3.0.1 multiformats: 10.0.2 dev: false @@ -1435,7 +1442,17 @@ packages: '@ipld/car': 5.0.0 '@ipld/dag-cbor': 8.0.0 '@ipld/dag-ucan': 2.0.1 - '@ucanto/interface': 3.0.0 + '@ucanto/interface': 3.0.1 + multiformats: 10.0.2 + dev: false + + /@ucanto/core/3.0.2: + resolution: {integrity: sha512-TEVCqAM/3v4fXLuZcIBgQZrPwD53yqoXqwmSChhd420FikFGkkAeWvj6JT6oR4VmCuiIPK5FnukaE2LL5h0Ekg==} + dependencies: + '@ipld/car': 5.0.0 + '@ipld/dag-cbor': 8.0.0 + '@ipld/dag-ucan': 2.0.1 + '@ucanto/interface': 3.0.1 multiformats: 10.0.2 dev: false @@ -1446,22 +1463,39 @@ packages: multiformats: 10.0.2 dev: false + /@ucanto/interface/3.0.1: + resolution: {integrity: sha512-1UlyLMjJwgzAmhlqu/V1gz0xrE9MUiI3gdzxOJbIXwrS7zAWsbtUZqIS/SPpr1+PYnNO8PHSGyGekb+N0dqtWQ==} + dependencies: + '@ipld/dag-ucan': 2.0.1 + multiformats: 10.0.2 + dev: false + /@ucanto/principal/3.0.0: resolution: {integrity: sha512-7CwVbYQc+CdWta+lNuI6vRjVT+GkPwf2VQVXFBm8i4fQomFOTmOq8I/Be3TBS9N2OaIbL7b/eKy1WBdMMzfz5g==} dependencies: '@ipld/dag-ucan': 2.0.1 '@noble/ed25519': 1.7.1 - '@ucanto/interface': 3.0.0 + '@ucanto/interface': 3.0.1 multiformats: 10.0.2 one-webcrypto: 1.0.3 dev: false - /@ucanto/server/3.0.1: - resolution: {integrity: sha512-PMBb9gPk+5+qKl7bANusPq9xCm2S0dVNIT33EmmtNhXWQSj8nLvWLInnxXYGc+ziyQonPZtDPgKi02uREFEdXw==} + /@ucanto/principal/3.0.1: + resolution: {integrity: sha512-0U0EF2ddfR55LKKc7FkzTkH8OFvjZvEeRqMkyV5FyeSsFEF7lXhgEXZrNgggK2zlriXjYC9VVCpPhsGb4cI72g==} dependencies: - '@ucanto/core': 3.0.1 - '@ucanto/interface': 3.0.0 - '@ucanto/validator': 3.0.1 + '@ipld/dag-ucan': 2.0.1 + '@noble/ed25519': 1.7.1 + '@ucanto/interface': 3.0.1 + multiformats: 10.0.2 + one-webcrypto: 1.0.3 + dev: false + + /@ucanto/server/3.0.4: + resolution: {integrity: sha512-4a5ou5HZ8ymw39EeZ0024nu0JD916xTMpYsS4eXMxpnoWlOjgmoeWZ5e01dEiw5AlfnSa8e9+a0b1dzvSISQxQ==} + dependencies: + '@ucanto/core': 3.0.2 + '@ucanto/interface': 3.0.1 + '@ucanto/validator': 3.0.4 dev: false /@ucanto/transport/3.0.1: @@ -1469,18 +1503,28 @@ packages: dependencies: '@ipld/car': 5.0.0 '@ipld/dag-cbor': 8.0.0 - '@ucanto/core': 3.0.1 - '@ucanto/interface': 3.0.0 + '@ucanto/core': 3.0.2 + '@ucanto/interface': 3.0.1 multiformats: 10.0.2 dev: false - /@ucanto/validator/3.0.1: - resolution: {integrity: sha512-LVirhuwMPOwATIDwlhGZt7C1BtrKp2+HJ7pALQcbC4+eHYyminniZEAzYjf0/EnjXtDj0SL3jnnBBvmpIJiWDQ==} + /@ucanto/transport/3.0.2: + resolution: {integrity: sha512-IyfI26VWPxCL2jnGiGP1i6mZblk8QORHzEVt5t+7Pic2k7pANQHoqbveQveRb9a8z6D/UdFogSPQxWYYtKaxWQ==} dependencies: '@ipld/car': 5.0.0 '@ipld/dag-cbor': 8.0.0 - '@ucanto/core': 3.0.1 - '@ucanto/interface': 3.0.0 + '@ucanto/core': 3.0.2 + '@ucanto/interface': 3.0.1 + multiformats: 10.0.2 + dev: false + + /@ucanto/validator/3.0.4: + resolution: {integrity: sha512-JG6y6yWPDUBoJuWP7auwMTZf9SJN9d2e7y/ZbVvluQBZC+WvhLq1Z2cjWCjA21Y2FJxWeI27leBjWzyIsHtYUA==} + dependencies: + '@ipld/car': 5.0.0 + '@ipld/dag-cbor': 8.0.0 + '@ucanto/core': 3.0.2 + '@ucanto/interface': 3.0.1 multiformats: 10.0.2 dev: false