diff --git a/packages/access-client/test/agent.test.js b/packages/access-client/test/agent.test.js index 6f9dd43a..44a66299 100644 --- a/packages/access-client/test/agent.test.js +++ b/packages/access-client/test/agent.test.js @@ -313,7 +313,7 @@ describe('Agent', function () { await bob.importSpaceFromDelegation(proof) await bob.setCurrentSpace(space.did()) - const proofs = bob.proofs([{ can: 'store/add', with: space.did() }]) + const proofs = bob.proofs([{ can: 'space/blob/add', with: space.did() }]) assert(proofs.length) }) @@ -354,7 +354,7 @@ describe('Agent', function () { 'RSA_DECRYPT_OAEP_3072_SHA256' ) } - const proofs = bob.proofs([{ can: 'store/add', with: space.did() }]) + const proofs = bob.proofs([{ can: 'space/blob/add', with: space.did() }]) assert(proofs.length) }) @@ -373,13 +373,13 @@ describe('Agent', function () { const proof = await alice.delegate({ audience: bob, audienceMeta: { name: 'videos', type: 'app' }, - abilities: ['store/add'], + abilities: ['space/blob/add'], }) await bob.importSpaceFromDelegation(proof) await bob.setCurrentSpace(space.did()) - const proofs = bob.proofs([{ can: 'store/add', with: space.did() }]) + const proofs = bob.proofs([{ can: 'space/blob/add', with: space.did() }]) assert(proofs.length) }) @@ -606,7 +606,7 @@ describe('Agent', function () { await alice.setCurrentSpace(space.did()) const delegation = await alice.delegate({ - abilities: ['store/add'], + abilities: ['space/blob/add'], audience: bob.issuer, audienceMeta: { name: 'sss', @@ -633,7 +633,7 @@ describe('Agent', function () { await bob.importSpaceFromDelegation(bobAuth) await bob.setCurrentSpace(bobSpace.did()) const bobDelegation = await bob.delegate({ - abilities: ['store/add'], + abilities: ['space/blob/add'], audience: mallory.issuer, audienceMeta: { name: 'sss', diff --git a/packages/access-client/test/encoding.test.js b/packages/access-client/test/encoding.test.js index 7d7d4829..c559a525 100644 --- a/packages/access-client/test/encoding.test.js +++ b/packages/access-client/test/encoding.test.js @@ -86,7 +86,7 @@ describe('Encoding', function () { audience: bob, capabilities: [ { - can: 'store/add', + can: 'space/blob/add', with: alice.did(), }, ], @@ -101,7 +101,7 @@ describe('Encoding', function () { assert.deepEqual(delegation.capabilities, [ { - can: 'store/add', + can: 'space/blob/add', with: alice.did(), }, ]) diff --git a/packages/capabilities/src/access.js b/packages/capabilities/src/access.js index 1a80380b..822b4fa1 100644 --- a/packages/capabilities/src/access.js +++ b/packages/capabilities/src/access.js @@ -119,7 +119,7 @@ export const claim = capability({ export const delegate = capability({ can: 'access/delegate', /** - * Field MUST be a space DID with a storage provider. Delegation will be stored just like any other DAG stored using store/add capability. + * Field MUST be a space DID with a storage provider. Delegation will be stored just like any other DAG stored using space/blob/add capability. * * @see https://github.com/storacha/specs/blob/main/w3-access.md#delegate-with */ @@ -179,8 +179,8 @@ function subsetsNbDelegations(claim, proof) { * Checks that set of requested capabilities is a subset of the capabilities * that had been allowed by the owner or the delegate. * - * ⚠️ This function does not currently check that say `store/add` is allowed - * when say `store/*` was delegated, because it seems very unlikely that we + * ⚠️ This function does not currently check that say `space/blob/add` is allowed + * when say `space/blob/*` was delegated, because it seems very unlikely that we * will ever encounter delegations for `access/authorize` at all. * * @param {Schema.Infer[]} claim diff --git a/packages/capabilities/src/index.js b/packages/capabilities/src/index.js index 99cffe88..46496b95 100644 --- a/packages/capabilities/src/index.js +++ b/packages/capabilities/src/index.js @@ -91,7 +91,6 @@ export const abilitiesAsStrings = [ UploadShard.shard.can, UploadShard.list.can, Store.store.can, - Store.add.can, Store.get.can, Store.remove.can, Store.list.can, diff --git a/packages/capabilities/src/space.js b/packages/capabilities/src/space.js index 9bd53094..be91e1bb 100644 --- a/packages/capabilities/src/space.js +++ b/packages/capabilities/src/space.js @@ -26,12 +26,11 @@ export const space = capability({ }) /** - * `space/info` can be derived from any of the `store/*` + * `space/info` can be derived from any of the `store/*` or `upload/*` * capability that has matching `with`. This allows store service * to identify account based on any user request. */ -export const info = Store.add - .or(Store.list) +export const info = Store.list .or(Store.remove) .or(Upload.add) .or(Upload.list) diff --git a/packages/capabilities/src/store.js b/packages/capabilities/src/store.js index b0e3de7f..de396de8 100644 --- a/packages/capabilities/src/store.js +++ b/packages/capabilities/src/store.js @@ -33,59 +33,6 @@ export const store = capability({ derives: equalWith, }) -/** - * `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. - * - * @deprecated - */ -export const add = capability({ - can: 'store/add', - /** - * DID of the (memory) space where CAR is intended to - * be stored. - */ - with: SpaceDID, - nb: Schema.struct({ - /** - * 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: CARLink, - /** - * 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(), - }), - derives: (claim, from) => { - const result = equalLink(claim, from) - if (result.error) { - return result - } else if (claim.nb.size !== undefined && from.nb.size !== undefined) { - return claim.nb.size > from.nb.size - ? fail(`Size constraint violation: ${claim.nb.size} > ${from.nb.size}`) - : ok({}) - } else { - return ok({}) - } - }, -}) - /** * Capability to get store metadata by shard CID. * Use to check for inclusion, or get shard size and origin @@ -171,7 +118,7 @@ export const list = capability({ }) /** @deprecated */ -export const all = add.or(remove).or(list) +export const all = remove.or(list) // ⚠️ We export imports here so they are not omitted in generated typedes // @see https://github.com/microsoft/TypeScript/issues/51548 diff --git a/packages/capabilities/src/types.ts b/packages/capabilities/src/types.ts index 5d642f3a..3a4914b4 100644 --- a/packages/capabilities/src/types.ts +++ b/packages/capabilities/src/types.ts @@ -877,53 +877,12 @@ export interface RecordNotFound extends Error { /** @deprecated */ export type Store = InferInvokedCapability /** @deprecated */ -export type StoreAdd = InferInvokedCapability -/** @deprecated */ export type StoreGet = InferInvokedCapability /** @deprecated */ export type StoreRemove = InferInvokedCapability /** @deprecated */ export type StoreList = InferInvokedCapability -/** @deprecated */ -export type StoreAddSuccess = StoreAddSuccessDone | StoreAddSuccessUpload - -/** @deprecated */ -export type StoreAddSuccessStatusUpload = 'upload' -/** @deprecated */ -export type StoreAddSuccessStatusDone = 'done' - -/** @deprecated */ -export interface StoreAddSuccessResult { - /** - * Status of the item to store. A "done" status indicates that it is not - * necessary to upload the item. An "upload" status indicates that the item - * should be uploaded to the provided URL. - */ - status: StoreAddSuccessStatusUpload | StoreAddSuccessStatusDone - /** - * Total bytes allocated in the space to accommodate this stored item. - * May be zero if the item is _already_ stored in _this_ space. - */ - allocated: number - /** DID of the space this item will be stored in. */ - with: DID - /** CID of the item. */ - link: CARLink -} - -/** @deprecated */ -export interface StoreAddSuccessDone extends StoreAddSuccessResult { - status: StoreAddSuccessStatusDone -} - -/** @deprecated */ -export interface StoreAddSuccessUpload extends StoreAddSuccessResult { - status: StoreAddSuccessStatusUpload - url: ToString - headers: Record -} - /** @deprecated */ export interface StoreRemoveSuccess { size: number @@ -1256,7 +1215,6 @@ export type ServiceAbilityArray = [ UploadShard['can'], UploadShardList['can'], Store['can'], - StoreAdd['can'], StoreGet['can'], StoreRemove['can'], StoreList['can'], diff --git a/packages/capabilities/src/upload.js b/packages/capabilities/src/upload.js index 78b52b89..b9ab86ea 100644 --- a/packages/capabilities/src/upload.js +++ b/packages/capabilities/src/upload.js @@ -41,11 +41,11 @@ const CARLink = Link.match({ code: CAR.code, version: 1 }) * 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 + * CAR files (shards) and invoke `space/blob/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. + * That said `upload/add` could be invoked without invoking `space/blob/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 diff --git a/packages/capabilities/src/utils.js b/packages/capabilities/src/utils.js index 007ce8c1..69fa04ea 100644 --- a/packages/capabilities/src/utils.js +++ b/packages/capabilities/src/utils.js @@ -83,7 +83,7 @@ export function containedWithin(child, parent, constraint) { } /** - * @template {API.ParsedCapability<"store/add"|"store/get"|"store/remove", API.URI<'did:'>, {link?: API.Link}>} T + * @template {API.ParsedCapability<"space/blob/add"|"space/blob/get"|"space/blob/remove"|"store/get"|"store/remove", API.URI<'did:'>, {link?: API.Link}>} T * @param {T} claimed * @param {T} delegated * @returns {API.Result<{}, API.Failure>} @@ -270,7 +270,7 @@ function parseAbility(ability) { /** * - * TODO: needs to account for caps derived from different namespaces like 'account/info' can be derived from 'store/add' + * TODO: needs to account for caps derived from different namespaces like 'account/info' can be derived from 'space/blob/add' * * @param {import('@ucanto/interface').Ability} parent * @param {import('@ucanto/interface').Ability} child diff --git a/packages/capabilities/test/capabilities/access.test.js b/packages/capabilities/test/capabilities/access.test.js index 9253c440..3ff534fd 100644 --- a/packages/capabilities/test/capabilities/access.test.js +++ b/packages/capabilities/test/capabilities/access.test.js @@ -235,7 +235,7 @@ describe('access capabilities', function () { with: alice.did(), nb: { iss: 'did:mailto:web.mail:alice', - att: [{ can: 'store/add' }], + att: [{ can: 'space/blob/add' }], }, proofs: [ await Access.authorize.delegate({ @@ -244,7 +244,7 @@ describe('access capabilities', function () { with: alice.did(), nb: { iss: 'did:mailto:web.mail:alice', - att: [{ can: 'store/add' }, { can: 'store/remove' }], + att: [{ can: 'space/blob/add' }, { can: 'space/blob/remove' }], }, }), ], @@ -594,7 +594,7 @@ describe('access capabilities', function () { nb: { iss: 'did:mailto:web.mail:alice', aud: bob.did(), - att: [{ can: 'store/add' }], + att: [{ can: 'space/blob/add' }], cause: parseLink('bafkqaaa'), }, proofs: [ @@ -604,7 +604,7 @@ describe('access capabilities', function () { with: alice.did(), nb: { iss: 'did:mailto:web.mail:alice', - att: [{ can: 'store/add' }, { can: 'store/remove' }], + att: [{ can: 'space/blob/add' }, { can: 'space/blob/remove' }], }, }), ], diff --git a/packages/capabilities/test/capabilities/store.test.js b/packages/capabilities/test/capabilities/store.test.js deleted file mode 100644 index 437d1e15..00000000 --- a/packages/capabilities/test/capabilities/store.test.js +++ /dev/null @@ -1,266 +0,0 @@ -import assert from 'assert' -import { access } from '@ucanto/validator' -import { Verifier } from '@ucanto/principal' -import { delegate, parseLink } from '@ucanto/core' -import * as Store from '../../src/store.js' -import * as Capability from '../../src/top.js' - -import { - alice, - service as w3, - mallory as account, - bob, -} from '../helpers/fixtures.js' -import { createCarCid, validateAuthorization } from '../helpers/utils.js' - -const CAR_LINK = parseLink( - 'bagbaierale63ypabqutmxxbz3qg2yzcp2xhz2yairorogfptwdd5n4lsz5xa' -) - -const top = async () => - Capability.top.delegate({ - issuer: account, - audience: alice, - with: account.did(), - }) - -const store = async () => - Store.store.delegate({ - issuer: account, - audience: alice, - with: account.did(), - proofs: [await top()], - }) - -describe('store capabilities', function () { - it('store/add can be derived from *', async () => { - const add = Store.add.invoke({ - issuer: alice, - audience: w3, - with: account.did(), - nb: { - link: CAR_LINK, - size: 0, - }, - proofs: [await top()], - }) - - const result = await access(await add.delegate(), { - capability: Store.add, - principal: Verifier, - authority: w3, - validateAuthorization, - }) - - if (result.error) { - assert.fail(result.error.message) - } - - assert.deepEqual(result.ok.audience.did(), w3.did()) - assert.equal(result.ok.capability.can, 'store/add') - assert.deepEqual(result.ok.capability.nb, { - link: CAR_LINK, - size: 0, - }) - }) - - it('store/add can be derived from store/*', async () => { - const add = Store.add.invoke({ - issuer: alice, - audience: w3, - with: account.did(), - nb: { - link: CAR_LINK, - size: 0, - }, - proofs: [await store()], - }) - - const result = await access(await add.delegate(), { - capability: Store.add, - principal: Verifier, - authority: w3, - validateAuthorization, - }) - - if (result.error) { - assert.fail(result.error.message) - } - - assert.deepEqual(result.ok.audience.did(), w3.did()) - assert.equal(result.ok.capability.can, 'store/add') - assert.deepEqual(result.ok.capability.nb, { - link: CAR_LINK, - size: 0, - }) - }) - - it('store/add can be derived from store/* derived from *', async () => { - const store = await Store.store.delegate({ - issuer: alice, - audience: bob, - with: account.did(), - proofs: [await top()], - }) - - const add = Store.add.invoke({ - issuer: bob, - audience: w3, - with: account.did(), - nb: { - link: CAR_LINK, - size: 0, - }, - proofs: [store], - }) - - const result = await access(await add.delegate(), { - capability: Store.add, - principal: Verifier, - authority: w3, - validateAuthorization, - }) - - if (result.error) { - assert.fail(result.error.message) - } - - assert.deepEqual(result.ok.audience.did(), w3.did()) - assert.equal(result.ok.capability.can, 'store/add') - assert.deepEqual(result.ok.capability.nb, { - link: CAR_LINK, - size: 0, - }) - }) - - it('store/add sholud fail when escalating size constraint', async () => { - const delegation = await Store.add.delegate({ - issuer: alice, - audience: bob, - with: account.did(), - nb: { - size: 1024, - }, - proofs: [await top()], - }) - - { - const add = Store.add.invoke({ - issuer: bob, - audience: w3, - with: account.did(), - nb: { - size: 1000, - link: CAR_LINK, - }, - proofs: [delegation], - }) - - const result = await access(await add.delegate(), { - capability: Store.add, - principal: Verifier, - authority: w3, - validateAuthorization, - }) - - if (result.error) { - assert.fail(result.error.message) - } - - assert.deepEqual(result.ok.audience.did(), w3.did()) - assert.equal(result.ok.capability.can, 'store/add') - assert.deepEqual(result.ok.capability.nb, { - link: CAR_LINK, - size: 1000, - }) - } - - { - const add = Store.add.invoke({ - issuer: bob, - audience: w3, - with: account.did(), - nb: { - size: 2048, - link: CAR_LINK, - }, - proofs: [delegation], - }) - - const result = await access(await add.delegate(), { - capability: Store.add, - principal: Verifier, - authority: w3, - validateAuthorization, - }) - - assert.ok(result.error) - assert(result.error.message.includes('violation: 2048 > 1024')) - } - }) - - const fixtures = [null, '1024', 12.24, true] - for (const size of fixtures) { - const json = JSON.stringify(size) - it(`store/add size must be an int not ${json}`, async () => { - const proofs = [await top()] - assert.throws(() => { - Store.add.invoke({ - issuer: alice, - audience: w3, - with: account.did(), - nb: { - link: CAR_LINK, - // @ts-expect-error - size, - }, - proofs, - }) - }, /Expected value of type/) - }) - - it(`store/add validation fails when size is ${json}`, async () => { - const add = await delegate({ - issuer: alice, - audience: w3, - capabilities: [ - { - can: 'store/add', - with: account.did(), - nb: { - link: await createCarCid('bafkqaaa'), - size, - }, - }, - ], - proofs: [await top()], - }) - - const result = await access(add, { - // @ts-expect-error - size type doesn't not match because we are testing fails - capability: Store.add, - principal: Verifier, - authority: w3, - }) - - assert.ok(result.error) - assert(result.error.message.includes('Expected value of type')) - }) - } - - it('store/add size must be an int', async () => { - const proofs = [await top()] - assert.throws(() => { - Store.add.invoke({ - issuer: alice, - audience: w3, - with: account.did(), - nb: { - link: CAR_LINK, - size: 1024.2, - }, - proofs, - }) - }, /Expected value of type integer instead got 1024\.2/) - }) -}) diff --git a/packages/cli/test/bin.spec.js b/packages/cli/test/bin.spec.js index d266a230..a02a87d9 100644 --- a/packages/cli/test/bin.spec.js +++ b/packages/cli/test/bin.spec.js @@ -1054,7 +1054,7 @@ export const testDelegation = { assert.equal(delegate.status.success(), true) }), - 'storacha delegation create -c store/add -c upload/add --base64': test( + 'storacha delegation create -c space/blob/add -c upload/add --base64': test( async (assert, context) => { const env = context.env.alice const { bob } = Test @@ -1065,7 +1065,7 @@ export const testDelegation = { 'create', bob.did(), '-c', - 'store/add', + 'space/blob/add', '-c', 'upload/add', '--base64', @@ -1081,7 +1081,7 @@ export const testDelegation = { const delegation = extractRes.ok assert.equal(delegation?.audience.did(), bob.did()) - assert.equal(delegation?.capabilities[0].can, 'store/add') + assert.equal(delegation?.capabilities[0].can, 'space/blob/add') assert.equal(delegation?.capabilities[0].with, spaceDID) assert.equal(delegation?.capabilities[1].can, 'upload/add') assert.equal(delegation?.capabilities[1].with, spaceDID) diff --git a/packages/upload-api/test/handlers/space-info.spec.js b/packages/upload-api/test/handlers/space-info.spec.js index 70500898..ebbbb141 100644 --- a/packages/upload-api/test/handlers/space-info.spec.js +++ b/packages/upload-api/test/handlers/space-info.spec.js @@ -76,45 +76,6 @@ describe('space/info', function () { } }) - it('should return space info with store/add as proof', async function () { - const { signer: issuer, service, connection } = ctx - - const { space, delegation } = await createSpace( - issuer, - service, - connection, - 'space-info@dag.house' - ) - - const inv = await Space.info - .invoke({ - issuer, - audience: service, - with: space.did(), - proofs: [ - await Store.add.delegate({ - audience: issuer, - issuer: space, - with: space.did(), - proofs: [delegation], - nb: { - size: 1000, - link: parseLink( - 'bagbaierale63ypabqutmxxbz3qg2yzcp2xhz2yairorogfptwdd5n4lsz5xa' - ), - }, - }), - ], - }) - .execute(connection) - - if (inv.out.error) { - assert.fail(inv.out.error.message) - } else { - assert.deepEqual(inv.out.ok.did, space.did()) - } - }) - it('should return space info with store/list as proof', async function () { const { signer: issuer, service, connection } = ctx diff --git a/packages/w3up-client/src/types.ts b/packages/w3up-client/src/types.ts index 68a899fd..7aa4d6b8 100644 --- a/packages/w3up-client/src/types.ts +++ b/packages/w3up-client/src/types.ts @@ -98,7 +98,6 @@ export type { SpaceBlobAdd, SpaceBlobList, SpaceBlobRemove, - StoreAdd, StoreList, StoreRemove, UploadAdd,