diff --git a/.github/release-please-config.json b/.github/release-please-config.json index d4f813ec..d2a2ce78 100644 --- a/.github/release-please-config.json +++ b/.github/release-please-config.json @@ -2,7 +2,6 @@ "plugins": [ "node-workspace" ], - "last-release-sha": "e6f8d809f4e06fc2920dcb28e1b5926bb73f4e46", "bootstrap-sha": "f814e75a89d3ed7c3488a8cb7af8d94f0cfba440", "packages": { "packages/principal": {}, @@ -10,7 +9,6 @@ "packages/core": {}, "packages/interface": {}, "packages/server": {}, - "packages/transport": {}, - "packages/validator": {} + "packages/transport": {} } } diff --git a/.github/release-please-manifest.json b/.github/release-please-manifest.json index 13d0f872..f0d68b69 100644 --- a/.github/release-please-manifest.json +++ b/.github/release-please-manifest.json @@ -1 +1,8 @@ -{"packages/client":"4.1.0","packages/core":"4.1.0","packages/interface":"4.1.0","packages/principal":"4.1.0","packages/server":"4.1.0","packages/transport":"4.1.0","packages/validator":"4.1.0"} \ No newline at end of file +{ + "packages/client": "4.1.0", + "packages/core": "4.1.0", + "packages/interface": "4.1.0", + "packages/principal": "4.1.0", + "packages/server": "4.1.0", + "packages/transport": "4.1.0" +} diff --git a/.github/workflows/server.yml b/.github/workflows/server.yml index 6a423b1f..f708a9aa 100644 --- a/.github/workflows/server.yml +++ b/.github/workflows/server.yml @@ -10,7 +10,6 @@ on: - 'packages/core/**' - 'packages/transport/**' - 'packages/client/**' - - 'packages/validator/**' - 'packages/server/**' pull_request: branches: @@ -20,7 +19,6 @@ on: - 'packages/core/**' - 'packages/transport/**' - 'packages/client/**' - - 'packages/validator/**' - 'packages/server/**' - '.github/workflows/server.yml' jobs: diff --git a/.github/workflows/validator.yml b/.github/workflows/validator.yml deleted file mode 100644 index e238a85f..00000000 --- a/.github/workflows/validator.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: validator - -on: - workflow_dispatch: - push: - branches: - - main - paths: - - 'packages/interface/**' - - 'packages/core/**' - - 'packages/transport/**' - - 'packages/client/**' - - 'packages/validator/**' - pull_request: - branches: - - main - paths: - - 'packages/interface/**' - - 'packages/core/**' - - 'packages/transport/**' - - 'packages/client/**' - - 'packages/validator/**' - - '.github/workflows/validator.yml' -jobs: - check: - name: Typecheck - runs-on: ubuntu-latest - strategy: - matrix: - node-version: - - 16 - project: - - validator - steps: - - uses: actions/checkout@v2 - - - name: Setup node ${{ matrix.node-version }} - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - - - name: Install dependencies - uses: pnpm/action-setup@v2.0.1 - id: pnpm-install - with: - version: 7 - run_install: true - - - name: Typecheck - uses: gozala/typescript-error-reporter-action@v1.0.8 - with: - project: packages/${{matrix.project}}/tsconfig.json - test: - name: Test - runs-on: ${{ matrix.os }} - - strategy: - matrix: - node-version: - - 14 - - 16 - os: - - ubuntu-latest - - windows-latest - - macos-latest - project: - - validator - - steps: - - uses: actions/checkout@v2 - - - name: Setup Node - uses: actions/setup-node@v2 - with: - node-version: ${{ matrix.node-version }} - - - name: Install dependencies - uses: pnpm/action-setup@v2.0.1 - id: pnpm-install - with: - version: 7 - run_install: true - - - name: Test (Node) - run: pnpm run --if-present --dir packages/${{matrix.project}} test:node - - - name: Test (Web) - run: pnpm run --if-present --dir packages/${{matrix.project}} test:web diff --git a/package.json b/package.json index 119db983..e8ae91f3 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,7 @@ "packages/client", "packages/server", "packages/transport", - "packages/principal", - "packages/validator" + "packages/principal" ], "scripts": { "format": "prettier --write '**/*.{js,ts,yml,json}' --ignore-path .gitignore", diff --git a/packages/core/package.json b/packages/core/package.json index 799a83d9..7faa16cc 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -38,9 +38,11 @@ "devDependencies": { "@types/chai": "^4.3.3", "@types/mocha": "^9.1.0", + "@types/chai-subset": "^1.3.3", "@ucanto/principal": "^4.1.0", "c8": "^7.11.0", "chai": "^4.3.6", + "chai-subset": "^1.6.0", "mocha": "^10.1.0", "nyc": "^15.1.0", "playwright-test": "^8.1.1", @@ -75,6 +77,22 @@ "./delegation": { "types": "./dist/src/delegation.d.ts", "import": "./src/delegation.js" + }, + "./schema": { + "types": "./dist/src/schema.d.ts", + "import": "./src/schema.js" + }, + "./capability": { + "types": "./dist/src/capability.d.ts", + "import": "./src/capability.js" + }, + "./validator": { + "types": "./dist/src/validator.d.ts", + "import": "./src/validator.js" + }, + "./error": { + "types": "./dist/src/error.d.ts", + "import": "./src/error.js" } }, "c8": { diff --git a/packages/validator/src/capability.js b/packages/core/src/capability.js similarity index 96% rename from packages/validator/src/capability.js rename to packages/core/src/capability.js index 68154db2..450c1f29 100644 --- a/packages/validator/src/capability.js +++ b/packages/core/src/capability.js @@ -7,7 +7,8 @@ import { DelegationError as MatchError, Failure, } from './error.js' -import { invoke, delegate } from '@ucanto/core' +import { invoke } from './invocation.js' +import { delegate } from './delegation.js' /** * @template {API.Ability} A @@ -114,6 +115,27 @@ class Capability extends Unit { this.descriptor = { derives, ...descriptor } } + /** + * @type {API.Reader} + */ + get with() { + return this.descriptor.with + } + + /** + * @param {unknown} source + */ + read(source) { + try { + const result = this.create(/** @type {any} */ (source)) + return /** @type {API.Result>, API.Failure>} */ ( + result + ) + } catch (error) { + return /** @type {any} */ (error) + } + } + /** * @param {API.InferCreateOptions>} options */ @@ -344,6 +366,13 @@ class Derive extends Unit { this.derives = derives } + /** + * @param {unknown} source + */ + read(source) { + return this.to.read(source) + } + /** * @type {typeof this.to['create']} */ @@ -365,6 +394,10 @@ class Derive extends Unit { get can() { return this.to.can } + get with() { + return this.to.with + } + /** * @param {API.Source} capability * @returns {API.MatchResult>} diff --git a/packages/validator/src/error.js b/packages/core/src/error.js similarity index 90% rename from packages/validator/src/error.js rename to packages/core/src/error.js index 82d2c000..64b8a378 100644 --- a/packages/validator/src/error.js +++ b/packages/core/src/error.js @@ -1,5 +1,4 @@ import * as API from '@ucanto/interface' -import { the } from './util.js' import { isLink } from 'multiformats/link' /** @@ -35,7 +34,8 @@ export class EscalatedCapability extends Failure { this.claimed = claimed this.delegated = delegated this.cause = cause - this.name = the('EscalatedCapability') + /** @type {'EscalatedCapability'} */ + this.name = 'EscalatedCapability' } describe() { return `Constraint violation: ${this.cause.message}` @@ -52,7 +52,8 @@ export class DelegationError extends Failure { */ constructor(causes, context) { super() - this.name = the('InvalidClaim') + /** @type {'InvalidClaim'} */ + this.name = 'InvalidClaim' this.causes = causes this.context = context } @@ -79,45 +80,6 @@ export class DelegationError extends Failure { } } -/** - * @implements {API.InvalidSignature} - */ -export class InvalidSignature extends Failure { - /** - * @param {API.Delegation} delegation - * @param {API.Verifier} verifier - */ - constructor(delegation, verifier) { - super() - this.name = the('InvalidSignature') - this.delegation = delegation - this.verifier = verifier - } - get issuer() { - return this.delegation.issuer - } - get audience() { - return this.delegation.audience - } - get key() { - return this.verifier.toDIDKey() - } - describe() { - const issuer = this.issuer.did() - const key = this.key - return ( - issuer.startsWith('did:key') - ? [ - `Proof ${this.delegation.cid} does not has a valid signature from ${key}`, - ] - : [ - `Proof ${this.delegation.cid} issued by ${issuer} does not has a valid signature from ${key}`, - ` ℹ️ Probably issuer signed with a different key, which got rotated, invalidating delegations that were issued with prior keys`, - ] - ).join('\n') - } -} - /** * @implements {API.UnavailableProof} */ @@ -128,7 +90,8 @@ export class UnavailableProof extends Failure { */ constructor(link, cause) { super() - this.name = the('UnavailableProof') + /** @type {'UnavailableProof'} */ + this.name = 'UnavailableProof' this.link = link this.cause = cause } @@ -149,7 +112,8 @@ export class DIDKeyResolutionError extends Failure { */ constructor(did, cause) { super() - this.name = the('DIDKeyResolutionError') + /** @type {'DIDKeyResolutionError'} */ + this.name = 'DIDKeyResolutionError' this.did = did this.cause = cause } @@ -171,7 +135,8 @@ export class InvalidAudience extends Failure { */ constructor(audience, delegation) { super() - this.name = the('InvalidAudience') + /** @type {'InvalidAudience'} */ + this.name = 'InvalidAudience' this.audience = audience this.delegation = delegation } @@ -201,7 +166,8 @@ export class MalformedCapability extends Failure { */ constructor(capability, cause) { super() - this.name = the('MalformedCapability') + /** @type {'MalformedCapability'} */ + this.name = 'MalformedCapability' this.capability = capability this.cause = cause } @@ -221,7 +187,8 @@ export class UnknownCapability extends Failure { */ constructor(capability) { super() - this.name = the('UnknownCapability') + /** @type {'UnknownCapability'} */ + this.name = 'UnknownCapability' this.capability = capability } /* c8 ignore next 3 */ @@ -236,7 +203,8 @@ export class Expired extends Failure { */ constructor(delegation) { super() - this.name = the('Expired') + /** @type {'Expired'} */ + this.name = 'Expired' this.delegation = delegation } describe() { @@ -259,13 +227,73 @@ export class Expired extends Failure { } } +/** + * @param {unknown} capability + * @param {string|number} [space] + */ + +const format = (capability, space) => + JSON.stringify( + capability, + (_key, value) => { + /* c8 ignore next 2 */ + if (isLink(value)) { + return value.toString() + } else { + return value + } + }, + space + ) + +/** + * @implements {API.InvalidSignature} + */ +export class InvalidSignature extends Failure { + /** + * @param {API.Delegation} delegation + * @param {API.Verifier} verifier + */ + constructor(delegation, verifier) { + super() + /** @type {'InvalidSignature'} */ + this.name = 'InvalidSignature' + this.delegation = delegation + this.verifier = verifier + } + get issuer() { + return this.delegation.issuer + } + get audience() { + return this.delegation.audience + } + get key() { + return this.verifier.toDIDKey() + } + describe() { + const issuer = this.issuer.did() + const key = this.key + return ( + issuer.startsWith('did:key') + ? [ + `Proof ${this.delegation.cid} does not has a valid signature from ${key}`, + ] + : [ + `Proof ${this.delegation.cid} issued by ${issuer} does not has a valid signature from ${key}`, + ` ℹ️ Probably issuer signed with a different key, which got rotated, invalidating delegations that were issued with prior keys`, + ] + ).join('\n') + } +} + export class NotValidBefore extends Failure { /** * @param {API.Delegation & { notBefore: number }} delegation */ constructor(delegation) { super() - this.name = the('NotValidBefore') + /** @type {'NotValidBefore'} */ + this.name = 'NotValidBefore' this.delegation = delegation } describe() { @@ -288,25 +316,6 @@ export class NotValidBefore extends Failure { } } -/** - * @param {unknown} capability - * @param {string|number} [space] - */ - -const format = (capability, space) => - JSON.stringify( - capability, - (_key, value) => { - /* c8 ignore next 2 */ - if (isLink(value)) { - return value.toString() - } else { - return value - } - }, - space - ) - /** * @param {string} message */ diff --git a/packages/core/src/lib.js b/packages/core/src/lib.js index 96492458..e9030adb 100644 --- a/packages/core/src/lib.js +++ b/packages/core/src/lib.js @@ -10,3 +10,7 @@ export { } from './link.js' export * as UCAN from '@ipld/dag-ucan' export * as DID from '@ipld/dag-ucan/did' +export * from './capability.js' +export * from './error.js' +export * as Schema from './schema.js' +export * from './protocol/protocol.js' diff --git a/packages/core/src/protocol/protocol.js b/packages/core/src/protocol/protocol.js new file mode 100644 index 00000000..aff6fdd3 --- /dev/null +++ b/packages/core/src/protocol/protocol.js @@ -0,0 +1,69 @@ +import * as The from './type.js' + +/** + * @template {[The.Task, ...The.Task[]]} Tasks + * @param {Tasks} tasks + * @returns {The.Protocol>} + */ +export const protocol = tasks => new Protocol(build(tasks)) + +/** + * @template {[The.Task, ...The.Task[]]} Tasks + * @param {Tasks} tasks + * @returns {The.InferAbilities} + */ +const build = tasks => { + const abilities = /** @type {The.InferAbilities} */ ({}) + + for (const task of tasks) { + const path = task.can.split('/') + if (path.length < 2) { + throw new RangeError( + `Expected task that has a valid 'can' field instead got '${task.can}'` + ) + } + const name = /** @type {string} */ (path.pop()) + const key = name === '*' ? '_' : name + const namespace = buildNamespace(abilities, path) + if (namespace[key] && namespace[key] !== task) { + throw new RangeError( + `All tasks must have unique 'can' fields, but multiple tasks with "can: '${task.can}'" had been provided` + ) + } + namespace[key] = task + } + + return abilities +} + +/** + * @template {Record} T + * @param {T} source + * @param {string[]} path + */ +const buildNamespace = (source, path) => { + /** @type {Record} */ + let target = source + for (const name of path) { + if (name !== '.') { + if (target[name] == null) { + target[name] = {} + } + target = /** @type {Record} */ (target[name]) + } + } + return target +} + +/** + * @template {The.TaskGroup} Abilities + * @implements {The.Protocol} + */ +class Protocol { + /** + * @param {Abilities} abilities + */ + constructor(abilities) { + this.abilities = abilities + } +} diff --git a/packages/validator/src/schema/type.js b/packages/core/src/protocol/type.js similarity index 100% rename from packages/validator/src/schema/type.js rename to packages/core/src/protocol/type.js diff --git a/packages/core/src/protocol/type.ts b/packages/core/src/protocol/type.ts new file mode 100644 index 00000000..63e8628a --- /dev/null +++ b/packages/core/src/protocol/type.ts @@ -0,0 +1,36 @@ +import type { Task } from '../schema.js' +import type { Ability } from '@ucanto/interface' + +export type { Task, Ability } + +export interface Protocol { + abilities: Abilities + // and( + // protocol: Protocol + // ): Protocol +} + +export type TaskGroup = { + [K: string]: Task | TaskGroup +} + +export type InferAbilities = Tasks extends [infer T] + ? InferAbility + : Tasks extends [infer T, ...infer TS] + ? InferAbility & InferAbilities + : never + +type InferAbility = T extends Task + ? InferNamespacedAbility + : never + +type InferNamespacedAbility< + Path extends string, + T extends Task +> = Path extends `./${infer Rest}` + ? InferNamespacedAbility + : Path extends `${infer Key}/${infer Rest}` + ? { [K in EscapeKey]: InferNamespacedAbility } + : { [K in EscapeKey]: T } + +type EscapeKey = Key extends '*' ? '_' : Key diff --git a/packages/validator/src/schema.js b/packages/core/src/schema.js similarity index 71% rename from packages/validator/src/schema.js rename to packages/core/src/schema.js index e2a5e547..2ee85725 100644 --- a/packages/validator/src/schema.js +++ b/packages/core/src/schema.js @@ -2,4 +2,6 @@ export * as URI from './schema/uri.js' export * as Link from './schema/link.js' export * as DID from './schema/did.js' export * as Text from './schema/text.js' +export { result } from './schema/result.js' export * from './schema/schema.js' +export * from './schema/task.js' diff --git a/packages/validator/src/schema/did.js b/packages/core/src/schema/did.js similarity index 100% rename from packages/validator/src/schema/did.js rename to packages/core/src/schema/did.js diff --git a/packages/validator/src/schema/link.js b/packages/core/src/schema/link.js similarity index 96% rename from packages/validator/src/schema/link.js rename to packages/core/src/schema/link.js index 80dd34c1..a458b650 100644 --- a/packages/validator/src/schema/link.js +++ b/packages/core/src/schema/link.js @@ -1,5 +1,5 @@ import * as API from '@ucanto/interface' -import { create, createLegacy, isLink, parse } from '@ucanto/core/link' +import { create, createLegacy, isLink, parse } from '../link.js' import * as Schema from './schema.js' export { create, createLegacy, isLink, parse } diff --git a/packages/core/src/schema/result.js b/packages/core/src/schema/result.js new file mode 100644 index 00000000..6ddad2ff --- /dev/null +++ b/packages/core/src/schema/result.js @@ -0,0 +1,20 @@ +import * as API from '@ucanto/interface' +import * as Schema from './schema.js' +export const fail = Schema.struct({ error: true }) + +/** + * Creates a schema for the task result by specifying ok and error types + * + * @template T + * @template {{}} [X={message:string}] + * @param {{ok: Schema.Reader, error?: Schema.Reader}} source + * @returns {Schema.Schema>} + */ +export const result = ({ + ok, + error = Schema.struct({ message: Schema.string() }), +}) => + Schema.or( + /** @type {Schema.Reader} */ (ok), + fail.and(error) + ) diff --git a/packages/validator/src/schema/schema.js b/packages/core/src/schema/schema.js similarity index 99% rename from packages/validator/src/schema/schema.js rename to packages/core/src/schema/schema.js index aee3e13a..8e4019bc 100644 --- a/packages/validator/src/schema/schema.js +++ b/packages/core/src/schema/schema.js @@ -128,7 +128,7 @@ export class API { // we also check that fallback is not undefined because that is the point // of having a fallback if (fallback === undefined) { - throw new Error(`Value of type undefined is not a vaild default`) + throw new Error(`Value of type undefined is not a valid default`) } const schema = new Default({ diff --git a/packages/core/src/schema/task.js b/packages/core/src/schema/task.js new file mode 100644 index 00000000..d20c0ba3 --- /dev/null +++ b/packages/core/src/schema/task.js @@ -0,0 +1,52 @@ +import * as API from '@ucanto/interface' +import { result } from './result.js' +import * as Schema from './type.js' + +/** + * @template {API.Capability} In - Input of the task, which (currently) + * corresponds to some capability. + * @template {{}} Ok - Ok type signifies successful task result. It encodes best + * practice by requiring empty map extension, this way API changes are rarely + * backwards incompatible & in most cases could be avoided using new named + * field. + * @template {{error:true}} [Error=API.Failure] - Error type signifies failed + * task result. It simply requires `error: true` field to allow differentiating + * from Ok type. + * + * @param {object} source + * @param {API.CapabilitySchema} source.in + * @param {API.Reader} source.ok + * @param {API.Reader} [source.error] + * @returns {Schema.Task>} + */ +export const task = source => new Task(source) + +/** + * Class is an implementation of {@link Schema.Task} interface. We use class so + * we could add some convenience methods. + * + * @template {API.Capability} In + * @template {{}} Ok + * @template {{error:true}} Error + */ +class Task { + /** + * @param {object} source + * @param {API.CapabilitySchema} source.in + * @param {API.Reader} source.ok + * @param {API.Reader} [source.error] + */ + constructor(source) { + this.source = source + this.out = result(source) + } + get can() { + return this.source.in.can + } + get with() { + return this.source.in.with + } + get in() { + return this.source.in + } +} diff --git a/packages/validator/src/schema/text.js b/packages/core/src/schema/text.js similarity index 100% rename from packages/validator/src/schema/text.js rename to packages/core/src/schema/text.js diff --git a/packages/validator/test/types.js b/packages/core/src/schema/type.js similarity index 100% rename from packages/validator/test/types.js rename to packages/core/src/schema/type.js diff --git a/packages/validator/src/schema/type.ts b/packages/core/src/schema/type.ts similarity index 92% rename from packages/validator/src/schema/type.ts rename to packages/core/src/schema/type.ts index 412dfa29..e6fab8e2 100644 --- a/packages/validator/src/schema/type.ts +++ b/packages/core/src/schema/type.ts @@ -1,4 +1,9 @@ -import { Failure as Error, Result, Phantom } from '@ucanto/interface' +import { + Failure as Error, + Result, + Capability, + Phantom, +} from '@ucanto/interface' export interface Reader< O = unknown, @@ -153,3 +158,14 @@ type RequiredKeys = { type OptionalKeys = { [k in keyof T]: undefined extends T[k] ? k : never }[keyof T] & {} + +export interface Task< + In extends Capability = Capability, + Out extends Result = Result +> { + can: In['can'] + with: Reader + in: Reader + + out: Reader +} diff --git a/packages/validator/src/schema/uri.js b/packages/core/src/schema/uri.js similarity index 100% rename from packages/validator/src/schema/uri.js rename to packages/core/src/schema/uri.js diff --git a/packages/validator/src/util.js b/packages/core/src/util.js similarity index 100% rename from packages/validator/src/util.js rename to packages/core/src/util.js diff --git a/packages/validator/src/lib.js b/packages/core/src/validator.js similarity index 98% rename from packages/validator/src/lib.js rename to packages/core/src/validator.js index 1c09eaab..709ee5ea 100644 --- a/packages/validator/src/lib.js +++ b/packages/core/src/validator.js @@ -1,32 +1,31 @@ import * as API from '@ucanto/interface' -import { isDelegation, UCAN } from '@ucanto/core' +// import { isDelegation, UCAN, Schema } from '@ucanto/core' +import { isDelegation } from './delegation.js' +import * as UCAN from '@ipld/dag-ucan' import { capability } from './capability.js' -import * as Schema from './schema.js' +import { DID, literal } from './schema.js' import { - UnavailableProof, - InvalidAudience, + InvalidSignature, Expired, NotValidBefore, - InvalidSignature, + UnavailableProof, + InvalidAudience, + DIDKeyResolutionError, DelegationError, Failure, MalformedCapability, - DIDKeyResolutionError, li, } from './error.js' +export { DID } export { Failure, UnavailableProof, MalformedCapability, + InvalidAudience, DIDKeyResolutionError as DIDResolutionError, } -export { capability } from './capability.js' -import { DID } from './schema.js' -export * from './schema.js' -export { Schema } - /** * @param {UCAN.Link} proof */ @@ -516,7 +515,7 @@ const resolveVerifier = async (did, delegation, config) => { const resolveDIDFromProofs = async (did, delegation, config) => { const update = Top.derive({ to: capability({ - with: Schema.literal(config.authority.did()), + with: literal(config.authority.did()), can: './update', nb: { key: DID.match({ method: 'key' }) }, }), @@ -542,5 +541,3 @@ const Top = capability({ const equalWith = (to, from) => to.with === from.with || new Failure(`Claimed ${to.with} can not be derived from ${from.with}`) - -export { InvalidAudience } diff --git a/packages/core/test/capabilities/access.js b/packages/core/test/capabilities/access.js new file mode 100644 index 00000000..a84e74ce --- /dev/null +++ b/packages/core/test/capabilities/access.js @@ -0,0 +1,47 @@ +import { _ } from './any.js' +import { capability, Schema } from '../../src/lib.js' +import { equalWith } from './util.js' + +/** + * Capability can only be delegated (but not invoked) allowing audience to + * derived any `access/` prefixed capability for the agent identified + * by did:key in the `with` field. + */ +export const access = _.derive({ + to: capability({ + can: 'access/*', + with: Schema.DID.match({ method: 'web' }), + }), + derives: equalWith, +}) + +/** + * Issued by trusted authority (usually the one handling invocation that contains this proof) + * to the account (aud) to update invocation local state of the document. + * + * @see https://github.com/web3-storage/specs/blob/main/w3-account.md#update + * + * @example + * ```js + * { + iss: "did:web:web3.storage", + aud: "did:mailto:alice@web.mail", + att: [{ + with: "did:web:web3.storage", + can: "./update", + nb: { key: "did:key:zAgent" } + }], + exp: null + sig: "..." + } + * ``` + */ +export const session = capability({ + can: './update', + // Should be web3.storage DID + with: Schema.DID.match({ method: 'web' }), + nb: { + // Agent DID so it can sign UCANs as did:mailto if it matches this delegation `aud` + key: Schema.DID.match({ method: 'key' }), + }, +}) diff --git a/packages/core/test/capabilities/any.js b/packages/core/test/capabilities/any.js new file mode 100644 index 00000000..6f04800d --- /dev/null +++ b/packages/core/test/capabilities/any.js @@ -0,0 +1,10 @@ +import { capability, Schema } from '../../src/lib.js' + +/** + * Represents the top `{ can: '*', with: 'did:key:zAlice' }` capability, which we often + * also call account linking. + */ +export const _ = capability({ + can: '*', + with: Schema.DID, +}) diff --git a/packages/core/test/capabilities/store.js b/packages/core/test/capabilities/store.js new file mode 100644 index 00000000..6e8a3966 --- /dev/null +++ b/packages/core/test/capabilities/store.js @@ -0,0 +1,150 @@ +import { capability, Failure, Schema } from '../../src/lib.js' +import { equalWith, equalLink } from './util.js' +import * as Any from './any.js' + +/** + * 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 _ = Any._.derive({ + to: capability({ + can: 'store/*', + /** + * did:key identifier of the (memory) space where CAR is intended to + * be stored. + */ + with: Schema.DID, + }), + /** + * `store/*` can be derived from the `*` capability as long as `with` field + * is the same. + */ + derives: equalWith, +}) + +// Right now ucanto does not yet has native `*` support, which means +// `store/add` can not be derived from `*` event though it can be +// derived from `store/*`. As a workaround we just define base capability +// here so all store capabilities could be derived from either `*` or +// `store/*`. +const base = _.or(Any._) + +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: Schema.DID.match({ method: 'key' }), + nb: { + /** + * 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: Schema.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: Schema.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 + ? new Failure( + `Size constraint violation: ${claim.nb.size} > ${from.nb.size}` + ) + : true + } else { + return true + } + }, + }), + /** + * `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: Schema.URI.match({ protocol: 'did:' }), + nb: { + /** + * CID of the CAR file to be removed from the store. + */ + link: Schema.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: Schema.URI.match({ protocol: 'did:' }), + nb: { + /** + * A pointer that can be moved back and forth on the list. + * It can be used to paginate a list for instance. + */ + cursor: Schema.string().optional(), + /** + * Maximum number of items per page. + */ + size: Schema.integer().optional(), + }, + derives: (claimed, delegated) => { + if (claimed.with !== delegated.with) { + return new Failure( + `Expected 'with: "${delegated.with}"' instead got '${claimed.with}'` + ) + } + return true + }, + }), + /** + * `store/list` can be derived from the `store/*` & `*` capability + * as long as the `with` fields match. + */ + derives: equalWith, +}) diff --git a/packages/core/test/capabilities/upload.js b/packages/core/test/capabilities/upload.js new file mode 100644 index 00000000..b8185565 --- /dev/null +++ b/packages/core/test/capabilities/upload.js @@ -0,0 +1,161 @@ +/** + * Upload Capabilities + * + * These can be imported directly with: + * ```js + * import * as Account from '@web3-storage/capabilities/upload' + * ``` + * + * @module + */ +import { capability, Schema } from '../../src/lib.js' +import { equalWith, fail, equal } from './util.js' +import { _ as top } from './any.js' + +/** + * Schema representing a link (a.k.a CID) to a CAR file. Enforces CAR codec code and CID v1. + */ +export const CARLink = Schema.Link.match({ code: 0x0202, version: 1 }) + +export const Space = Schema.DID.match({ method: 'key ' }) + +/** + * 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 _ = top.derive({ + to: capability({ + can: 'upload/*', + /** + * did:key identifier of the (memory) space where upload is add to the + * upload list. + */ + with: Space, + derives: equalWith, + }), + /** + * `upload/*` can be derived from the `*` capability as long as `with` field + * is the same. + */ + derives: equalWith, +}) + +// Right now ucanto does not yet has native `*` support, which means +// `upload/add` can not be derived from `*` event though it can be +// derived from `upload/*`. As a workaround we just define base capability +// here so all store capabilities could be derived from either `*` or +// `upload/*`. +const base = top.or(_) + +/** + * 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: Space, + nb: { + /** + * Root CID of the DAG to be added to the upload list. + */ + root: Schema.Link, + /** + * CIDs to the CAR files that contain blocks of the DAG. + */ + shards: CARLink.array().optional(), + }, + derives: (self, from) => { + return ( + fail(equalWith(self, from)) || + fail(equal(self.nb.root, from.nb.root, 'root')) || + fail(equal(self.nb.shards, from.nb.shards, 'shards')) || + true + ) + }, + }), + /** + * `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: Space, + nb: { + /** + * Root CID of the DAG to be removed from the upload list. + */ + root: Schema.Link, + }, + derives: (self, from) => { + return ( + fail(equalWith(self, from)) || + fail(equal(self.nb.root, from.nb.root, 'root')) || + true + ) + }, + }), + /** + * `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: Space, + nb: { + /** + * A pointer that can be moved back and forth on the list. + * It can be used to paginate a list for instance. + */ + cursor: Schema.string().optional(), + /** + * Maximum number of items per page. + */ + size: Schema.integer().optional(), + }, + }), + /** + * `upload/list` can be derived from the `upload/*` & `*` capability + * as long as with fields match. + */ + derives: equalWith, +}) diff --git a/packages/validator/test/util.js b/packages/core/test/capabilities/util.js similarity index 51% rename from packages/validator/test/util.js rename to packages/core/test/capabilities/util.js index b7874a71..e4ba5cab 100644 --- a/packages/validator/test/util.js +++ b/packages/core/test/capabilities/util.js @@ -1,10 +1,30 @@ -import { Failure } from '../src/error.js' import * as API from '@ucanto/interface' +import { Failure } from '../../src/lib.js' /** - * @param {API.Failure|true} value + * @template {API.ParsedCapability<"store/add"|"store/remove", API.URI<'did:'>, {link?: API.Link}>} T + * @param {T} claimed + * @param {T} delegated + * @returns {API.Result} */ -export const fail = value => (value === true ? undefined : value) +export const equalLink = (claimed, delegated) => { + if (claimed.with !== delegated.with) { + return new Failure( + `Expected 'with: "${delegated.with}"' instead got '${claimed.with}'` + ) + } else if ( + delegated.nb.link && + `${delegated.nb.link}` !== `${claimed.nb.link}` + ) { + return new Failure( + `Link ${claimed.nb.link ? `${claimed.nb.link}` : ''} violates imposed ${ + delegated.nb.link + } constraint.` + ) + } else { + return true + } +} /** * Check URI can be delegated @@ -42,7 +62,6 @@ export const canDelegateLink = (child, parent) => { ? true : new Failure(`${child} is different from ${parent}`) } - /** * Checks that `with` on claimed capability is the same as `with` * in delegated capability. Note this will ignore `can` field. @@ -58,3 +77,28 @@ export function equalWith(child, parent) { ) ) } + +/** + * @param {unknown} child + * @param {unknown} parent + * @param {string} constraint + */ + +export function equal(child, parent, constraint) { + if (parent === undefined || parent === '*') { + return true + } else if (String(child) === String(parent)) { + return true + } else { + return new Failure( + `Constrain violation: ${child} violates imposed ${constraint} constraint ${parent}` + ) + } +} + +/** + * @param {API.Failure | true} value + */ +export function fail(value) { + return value === true ? undefined : value +} diff --git a/packages/validator/test/voucher.js b/packages/core/test/capabilities/voucher.js similarity index 88% rename from packages/validator/test/voucher.js rename to packages/core/test/capabilities/voucher.js index e0228b26..29f4d63c 100644 --- a/packages/validator/test/voucher.js +++ b/packages/core/test/capabilities/voucher.js @@ -1,5 +1,7 @@ import { equalWith, canDelegateURI, canDelegateLink, fail } from './util.js' -import { capability, URI, Text, Link, DID } from '../src/lib.js' +import { capability, Schema } from '../../src/lib.js' +const { URI, Text, Link, DID } = Schema +export * from './voucher/types.js' export const Voucher = capability({ can: 'voucher/*', diff --git a/packages/core/test/capabilities/voucher/types.js b/packages/core/test/capabilities/voucher/types.js new file mode 100644 index 00000000..e69de29b diff --git a/packages/validator/test/types.ts b/packages/core/test/capabilities/voucher/types.ts similarity index 100% rename from packages/validator/test/types.ts rename to packages/core/test/capabilities/voucher/types.ts diff --git a/packages/validator/test/capability.spec.js b/packages/core/test/capability.spec.js similarity index 95% rename from packages/validator/test/capability.spec.js rename to packages/core/test/capability.spec.js index d5e69cdc..32294a0a 100644 --- a/packages/validator/test/capability.spec.js +++ b/packages/core/test/capability.spec.js @@ -1,11 +1,13 @@ -import { capability, URI, Link, Schema } from '../src/lib.js' -import { invoke, parseLink } from '@ucanto/core' +import { capability, Schema } from '../src/lib.js' +import { invoke, parseLink } from '../src/lib.js' import * as API from '@ucanto/interface' import { Failure } from '../src/error.js' import { the } from '../src/util.js' import { test, assert } from './test.js' import { alice, bob, mallory, service as w3 } from './fixtures.js' +const { URI, Link } = Schema + /** * @template {API.Capabilities} C * @param {C} capabilities @@ -42,6 +44,8 @@ test('capability selects matches', () => { }, }) + assert.deepEqual(read.with, URI.match({ protocol: 'file:' })) + const d1 = delegate([ { can: 'file/read', with: 'space://zAlice' }, { can: 'file/write', with: 'file:///home/zAlice/' }, @@ -214,6 +218,8 @@ test('derived capability chain', () => { }, }) + assert.deepEqual(register.with, URI.match({ protocol: 'mailto:' })) + const d1 = delegate([ { can: 'account/register', @@ -2064,3 +2070,114 @@ test('default derive with nb', () => { } ) }) + +test('capability .read', () => { + const data = URI.match({ protocol: 'data:' }) + const echo = capability({ + can: 'test/echo', + with: URI.match({ protocol: 'did:' }), + nb: { + message: URI.match({ protocol: 'data:' }), + }, + }) + + assert.match( + echo + .read({ + with: 'file://gozala/path', + nb: { + message: 'data:hello', + }, + bar: 1, + }) + .toString(), + /Invalid 'with' - Expected did: URI/ + ) + assert.match( + echo + .read({ + with: 'file://gozala/path', + nb: { + message: 'data:hello', + }, + bar: 1, + }) + .toString(), + /Invalid 'with' - Expected did: URI/ + ) + + assert.match( + echo + .read({ + with: alice.did(), + }) + .toString(), + /Invalid 'nb.message' - Expected URI but got undefined/ + ) + + assert.match( + echo + .read({ + with: alice.did(), + nb: { + message: 'echo:foo', + }, + }) + .toString(), + /Invalid 'nb.message' - Expected data: URI instead got echo:foo/ + ) + + assert.deepEqual( + echo.create({ with: alice.did(), nb: { message: 'data:hello' } }), + { + can: 'test/echo', + with: alice.did(), + nb: { + message: 'data:hello', + }, + } + ) + + assert.deepEqual( + echo.read({ + with: new URL(alice.did()), + nb: { message: 'data:hello' }, + }), + { + can: 'test/echo', + with: alice.did(), + nb: { + message: 'data:hello', + }, + } + ) +}) + +test('derived capability .read', () => { + const A = capability({ + can: 'invoke/a', + with: Schema.URI, + }) + + const AA = A.derive({ + to: capability({ + can: 'derive/a', + with: Schema.URI, + }), + derives: (b, a) => + b.with === a.with ? true : new Failure(`with don't match`), + }) + + assert.equal(AA.can, 'derive/a') + assert.deepEqual(AA.with, Schema.URI) + + assert.deepEqual( + AA.read({ + with: 'data:a', + }), + { + can: 'derive/a', + with: 'data:a', + } + ) +}) diff --git a/packages/validator/test/delegate.spec.js b/packages/core/test/delegate.spec.js similarity index 97% rename from packages/validator/test/delegate.spec.js rename to packages/core/test/delegate.spec.js index 16ff551e..8adea1ae 100644 --- a/packages/validator/test/delegate.spec.js +++ b/packages/core/test/delegate.spec.js @@ -1,12 +1,18 @@ -import { capability, DID, URI, Link, unknown, Schema } from '../src/lib.js' -import { invoke, parseLink, delegate, UCAN } from '@ucanto/core' +import { + capability, + Schema, + invoke, + parseLink, + delegate, + UCAN, +} from '../src/lib.js' import * as API from '@ucanto/interface' import { Failure } from '../src/error.js' import { the } from '../src/util.js' import { CID } from 'multiformats' import { test, assert } from './test.js' import { alice, bob, mallory, service as w3 } from './fixtures.js' - +const { DID, URI, Link } = Schema const echo = capability({ can: 'test/echo', with: DID.match({ method: 'key' }), diff --git a/packages/validator/test/error.spec.js b/packages/core/test/error.spec.js similarity index 98% rename from packages/validator/test/error.spec.js rename to packages/core/test/error.spec.js index 32ac898b..281e95a6 100644 --- a/packages/validator/test/error.spec.js +++ b/packages/core/test/error.spec.js @@ -8,7 +8,7 @@ import { NotValidBefore, } from '../src/error.js' import { alice, bob, mallory, service as w3 } from './fixtures.js' -import { delegate, UCAN } from '@ucanto/core' +import { delegate, UCAN } from '../src/lib.js' test('Failure', () => { const error = new Failure('boom!') diff --git a/packages/validator/test/extra-schema.spec.js b/packages/core/test/extra-schema.spec.js similarity index 100% rename from packages/validator/test/extra-schema.spec.js rename to packages/core/test/extra-schema.spec.js diff --git a/packages/validator/test/inference.spec.js b/packages/core/test/inference.spec.js similarity index 93% rename from packages/validator/test/inference.spec.js rename to packages/core/test/inference.spec.js index 3825d84b..1bf57b96 100644 --- a/packages/validator/test/inference.spec.js +++ b/packages/core/test/inference.spec.js @@ -1,12 +1,14 @@ -import * as Voucher from './voucher.js' +import * as Voucher from './capabilities/voucher.js' import { test, assert } from './test.js' import { alice, bob, mallory, service as w3 } from './fixtures.js' -import { capability, URI, Link, DID } from '../src/lib.js' -import * as API from './types.js' +import { capability, Schema } from '../src/lib.js' +import * as API from '@ucanto/interface' -test('execute capabilty', () => +const { URI, Link, DID } = Schema + +test('execute capability', () => /** - * @param {API.ConnectionView} connection + * @param {API.ConnectionView} connection */ async connection => { const claim = Voucher.Claim.invoke({ @@ -55,7 +57,7 @@ test('execute capabilty', () => test('can access fields on the proof', () => /** - * @param {API.Delegation<[API.VoucherRedeem]>} proof + * @param {API.Delegation<[Voucher.VoucherRedeem]>} proof */ proof => { const redeem = Voucher.Redeem.invoke({ @@ -73,7 +75,7 @@ test('can access fields on the proof', () => test('use InferInvokedCapability', () => /** - * @param {API.ConnectionView} connection + * @param {API.ConnectionView} connection * @param {API.InferInvokedCapability} capability */ async (connection, capability) => { diff --git a/packages/validator/test/mailto.spec.js b/packages/core/test/mailto.spec.js similarity index 91% rename from packages/validator/test/mailto.spec.js rename to packages/core/test/mailto.spec.js index 2a9f22e9..dd16ac84 100644 --- a/packages/validator/test/mailto.spec.js +++ b/packages/core/test/mailto.spec.js @@ -1,10 +1,7 @@ import { test, assert } from './test.js' -import { access, DID } from '../src/lib.js' -import { capability, URI, Link, Schema } from '../src/lib.js' -import { Failure } from '../src/error.js' +import { access, DID } from '../src/validator.js' +import { capability, delegate } from '../src/lib.js' import { ed25519, Verifier } from '@ucanto/principal' -import * as Client from '@ucanto/client' -import * as Core from '@ucanto/core' import { alice, bob, mallory, service } from './fixtures.js' const w3 = service.withDID('did:web:web3.storage') @@ -63,7 +60,7 @@ test('delegated ./update', async () => { const manager = await ed25519.generate() const worker = await ed25519.generate() - const authority = await Core.delegate({ + const authority = await delegate({ issuer: manager, audience: worker, capabilities: [ @@ -74,7 +71,7 @@ test('delegated ./update', async () => { ], expiration: Infinity, proofs: [ - await Core.delegate({ + await delegate({ issuer: w3, audience: manager, capabilities: [ @@ -156,7 +153,7 @@ test('fail invalid ./update proof', async () => { with: w3.did(), nb: { key: alice.did() }, proofs: [ - await Core.delegate({ + await delegate({ issuer: w3, audience: service, capabilities: [ diff --git a/packages/core/test/protocol.spec.js b/packages/core/test/protocol.spec.js new file mode 100644 index 00000000..e6fb4d2f --- /dev/null +++ b/packages/core/test/protocol.spec.js @@ -0,0 +1,161 @@ +import { test, assert } from './test.js' +import { capability, Failure, Schema, protocol } from '../src/lib.js' +import * as API from '@ucanto/interface' +import * as Store from './capabilities/store.js' +import * as Upload from './capabilities/upload.js' +import * as Access from './capabilities/access.js' +import { access } from '../src/validator.js' + +/** + * @template T + * @param {API.Reader} item + */ +const list = item => + Schema.struct({ + cursor: Schema.string().optional(), + size: Schema.integer(), + results: Schema.array(item), + }) + +const car = Schema.struct({ + link: Schema.Link, + size: Schema.integer(), + origin: Schema.Link.optional(), +}) + +const unit = Schema.struct({}) + +const up = Schema.struct({ + root: Schema.Link, + shards: Upload.CARLink.array().optional(), +}) + +const CARAdded = Schema.struct({ + status: 'done', + with: Schema.DID.match({ method: 'key' }), + link: Schema.Link, +}) + +const CARReceiving = Schema.struct({ + status: 'upload', + with: Schema.DID.match({ method: 'key' }), + link: Schema.Link, + url: Schema.URI, +}) + +// roughly based on https://github.com/web3-storage/w3protocol/blob/6e83725072ee093dda16549675b9ac943ea096b7/packages/upload-client/src/types.ts#L30-L41 + +const store = { + add: Schema.task({ + in: Store.add, + ok: CARAdded.or(CARReceiving), + }), + list: Schema.task({ + in: Store.list, + ok: list(car), + }), + remove: Schema.task({ + in: Store.remove, + ok: unit, + }), +} + +const upload = { + add: Schema.task({ + in: Upload.add, + ok: up, + }), + list: Schema.task({ + in: Upload.list, + ok: list(up), + }), + remove: Schema.task({ + in: Upload.remove, + ok: up, + }), +} + +const ucanto = { + update: Schema.task({ + in: Access.session, + ok: Schema.struct({}), + }), +} + +test('task api', () => { + assert.deepInclude(store.add, { + can: 'store/add', + with: Schema.DID.match({ method: 'key' }), + in: Store.add, + out: Schema.result({ ok: CARAdded.or(CARReceiving) }), + }) + + assert.deepInclude(store.remove, { + can: 'store/remove', + with: Schema.URI.match({ protocol: 'did:' }), + in: Store.remove, + out: Schema.result({ ok: unit }), + }) +}) + +test('protocol derives capabilities', () => { + const w3Store = protocol([store.add, store.list, store.remove]) + + assert.deepEqual(w3Store.abilities, { store }) + + const w3 = protocol([ + store.add, + store.list, + store.remove, + upload.add, + upload.list, + upload.remove, + ]) + + assert.deepEqual(w3.abilities, { store, upload }) +}) + +test('protocol handles ./update', () => { + const w3 = protocol([store.add, store.list, store.remove, ucanto.update]) + + assert.deepEqual(w3.abilities, { store, ...ucanto }) +}) + +test('conflicting capabilities', () => { + assert.throws( + () => + protocol([ + store.add, + store.list, + Schema.task({ in: Store.add, ok: Schema.struct({}) }), + ]), + /multiple tasks with "can: 'store\/add'/ + ) +}) + +test('requires namespace', () => { + assert.throws( + () => + protocol([ + Schema.task({ + in: capability({ + // @ts-expect-error + can: 'boom', + with: Schema.DID, + nb: {}, + }), + ok: Schema.struct({}), + }), + ]), + /valid 'can' field instead got 'boom'/ + ) +}) + +test('maps * to _', () => { + const any = Schema.task({ in: Store._, ok: Store._ }) + const w3 = protocol([store.add, store.list, store.remove, any]) + + assert.deepEqual(w3.abilities, { + store: { ...store, _: any }, + }) +}) diff --git a/packages/validator/test/schema.spec.js b/packages/core/test/schema.spec.js similarity index 99% rename from packages/validator/test/schema.spec.js rename to packages/core/test/schema.spec.js index 927e9d64..9b264f22 100644 --- a/packages/validator/test/schema.spec.js +++ b/packages/core/test/schema.spec.js @@ -4,7 +4,6 @@ import fixtures from './schema/fixtures.js' for (const { input, schema, expect, inputLabel, skip, only } of fixtures()) { const unit = skip ? test.skip : only ? test.only : test - unit(`${schema}.read(${inputLabel})`, () => { const result = schema.read(input) @@ -273,7 +272,6 @@ test('.key & .value of dictionary', () => { assert.deepEqual(Schema.dictionary({ value }).key, Schema.string()) }) - test('struct', () => { const Point = Schema.struct({ type: 'Point', @@ -597,7 +595,7 @@ test('default throws on invalid default', () => { test('unknown with default', () => { assert.throws( () => Schema.unknown().default(undefined), - /undefined is not a vaild default/ + /undefined is not a valid default/ ) }) diff --git a/packages/validator/test/schema/fixtures.js b/packages/core/test/schema/fixtures.js similarity index 98% rename from packages/validator/test/schema/fixtures.js rename to packages/core/test/schema/fixtures.js index 2c8aa303..4794a81d 100644 --- a/packages/validator/test/schema/fixtures.js +++ b/packages/core/test/schema/fixtures.js @@ -22,7 +22,7 @@ import { string, unknown } from '../../src/schema.js' * never: ExpectGroup * string: ExpectGroup, * boolean: ExpectGroup - * strartsWithHello: ExpectGroup + * startsWithHello: ExpectGroup * endsWithWorld: ExpectGroup * startsWithHelloEndsWithWorld: ExpectGroup * number: ExpectGroup @@ -71,9 +71,9 @@ export const fixture = ({ in: input, got = input, array, ...expect }) => ({ never: { any: fail({ expect: 'never', got }), ...expect.never }, string: { any: fail({ expect: 'string', got }), ...expect.string }, boolean: { any: fail({ expect: 'boolean', got }), ...expect.boolean }, - strartsWithHello: { + startsWithHello: { any: fail({ expect: 'string', got }), - ...expect.strartsWithHello, + ...expect.startsWithHello, }, endsWithWorld: { any: fail({ expect: 'string', got }), @@ -147,7 +147,7 @@ export const source = [ unknown: { any: pass() }, literal: { hello: { any: pass() } }, stringOrNumber: { any: pass() }, - strartsWithHello: { any: fail.as(`expect .* "Hello" .* got "hello"`) }, + startsWithHello: { any: fail.as(`expect .* "Hello" .* got "hello"`) }, endsWithWorld: { any: fail.as(`expect .* "world" .* got "hello"`) }, startsWithHelloEndsWithWorld: { any: fail.as(`expect .* "Hello" .* got "hello"`), @@ -159,7 +159,7 @@ export const source = [ string: { any: pass() }, unknown: { any: pass() }, stringOrNumber: { any: pass() }, - strartsWithHello: { any: fail.as(`expect .* "Hello" .* got "Green"`) }, + startsWithHello: { any: fail.as(`expect .* "Hello" .* got "Green"`) }, endsWithWorld: { any: fail.as(`expect .* "world" .* got "Green"`) }, startsWithHelloEndsWithWorld: { any: fail.as(`expect .* "Hello" .* got "Green"`), @@ -174,7 +174,7 @@ export const source = [ string: { any: pass() }, unknown: { any: pass() }, stringOrNumber: { any: pass() }, - strartsWithHello: { any: pass() }, + startsWithHello: { any: pass() }, endsWithWorld: { any: pass() }, startsWithHelloEndsWithWorld: { any: pass(), @@ -864,7 +864,7 @@ export const scenarios = fixture => [ }, { schema: Schema.string().startsWith('Hello'), - expect: fixture.strartsWithHello.any || fixture.string.any || fixture.any, + expect: fixture.startsWithHello.any || fixture.string.any || fixture.any, }, { schema: Schema.string().endsWith('world'), @@ -904,12 +904,10 @@ export const scenarios = fixture => [ expect: fixture.intDict?.any || fixture.dict?.any || fixture.any, }, - { schema: Schema.dictionary({ value: unknown() }), expect: fixture.dict?.any || fixture.any, }, - { schema: Schema.dictionary({ value: unknown(), diff --git a/packages/validator/test/schema/util.js b/packages/core/test/schema/util.js similarity index 100% rename from packages/validator/test/schema/util.js rename to packages/core/test/schema/util.js diff --git a/packages/core/test/test.js b/packages/core/test/test.js index d86c1160..dbe6d8ec 100644 --- a/packages/core/test/test.js +++ b/packages/core/test/test.js @@ -1,4 +1,6 @@ import { assert, use } from 'chai' +import subset from 'chai-subset' +use(subset) export const test = it export { assert } diff --git a/packages/validator/test/lib.spec.js b/packages/core/test/validator.spec.js similarity index 97% rename from packages/validator/test/lib.spec.js rename to packages/core/test/validator.spec.js index 224c184d..e4c0fda8 100644 --- a/packages/validator/test/lib.spec.js +++ b/packages/core/test/validator.spec.js @@ -1,13 +1,12 @@ import { test, assert } from './test.js' -import { access, claim } from '../src/lib.js' -import { capability, URI, Link } from '../src/lib.js' -import { Failure } from '../src/error.js' +import { access, claim } from '../src/validator.js' +import { capability, delegate } from '../src/lib.js' +import { URI, Link } from '../src/schema.js' +import { Failure, UnavailableProof } from '../src/error.js' import { Verifier } from '@ucanto/principal' -import * as Client from '@ucanto/client' import { alice, bob, mallory, service, service as w3 } from './fixtures.js' -import { UCAN, DID as Principal } from '@ucanto/core' -import { UnavailableProof } from '../src/error.js' +import { UCAN, DID as Principal } from '../src/lib.js' const storeAdd = capability({ can: 'store/add', @@ -156,7 +155,7 @@ test('unauthorized / invalid signature', async () => { }) test('unauthorized / unknown capability', async () => { - const invocation = await Client.delegate({ + const invocation = await delegate({ issuer: alice, audience: w3, capabilities: [ @@ -436,7 +435,7 @@ test('invalid claim / invalid signature', async () => { }) test('invalid claim / unknown capability', async () => { - const delegation = await Client.delegate({ + const delegation = await delegate({ issuer: alice, audience: bob, capabilities: [ @@ -477,7 +476,7 @@ test('invalid claim / unknown capability', async () => { test('invalid claim / malformed capability', async () => { const badDID = `bib:${alice.did().slice(4)}` - const delegation = await Client.delegate({ + const delegation = await delegate({ issuer: alice, audience: bob, capabilities: [ @@ -489,7 +488,7 @@ test('invalid claim / malformed capability', async () => { }) const nb = { link: Link.parse('bafkqaaa') } - const invocation = await Client.delegate({ + const invocation = await delegate({ issuer: bob, audience: w3, capabilities: [ diff --git a/packages/interface/src/capability.ts b/packages/interface/src/capability.ts index bee368a1..943abc5f 100644 --- a/packages/interface/src/capability.ts +++ b/packages/interface/src/capability.ts @@ -165,8 +165,15 @@ export type InferCaveatParams = keyof T extends never [K in keyof T]: T[K] extends { toJSON(): infer U } ? U : T[K] } +export interface CapabilitySchema extends Reader { + readonly can: T['can'] + + readonly with: Reader +} + export interface TheCapabilityParser> - extends CapabilityParser { + extends CapabilityParser, + CapabilitySchema { readonly can: M['value']['can'] create( diff --git a/packages/server/package.json b/packages/server/package.json index ac87d567..65a750a8 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -29,8 +29,7 @@ }, "dependencies": { "@ucanto/core": "^4.1.0", - "@ucanto/interface": "^4.1.0", - "@ucanto/validator": "^4.1.0" + "@ucanto/interface": "^4.1.0" }, "devDependencies": { "@types/chai": "^4.3.3", diff --git a/packages/server/src/agent.js b/packages/server/src/agent.js new file mode 100644 index 00000000..9b5d3bc2 --- /dev/null +++ b/packages/server/src/agent.js @@ -0,0 +1,56 @@ +import * as API from '@ucanto/interface' + +/** + * @template {API.DID} ID + * @param {{ + * signer: API.Signer + * authority?: API.Principal + * proofs?: API.Delegation[] + * }} options + */ +export const create = ({ signer, authority = signer, proofs = [] }) => + new Agent({ signer, authority, proofs, context: {} }) + +/** + * @template {API.DID} ID + * @template {{}} Context + */ +class Agent { + /** + * @param {object} options + * @param {API.Signer} options.signer + * @param {API.Principal} options.authority + * @param {API.Delegation[]} options.proofs + * @param {Context} options.context + */ + constructor(options) { + this.options = options + } + get context() { + return this.options.context + } + + did() { + return this.options.signer.did() + } + + /** + * @template T + * @param {API.ByteView} payload + */ + + sign(payload) { + return this.options.signer.sign(payload) + } + /** + * @template {{}} Extra + * @param {Extra} extra + * @returns {Agent} + */ + with(extra) { + return new Agent({ + ...this.options, + context: { ...this.options.context, ...extra }, + }) + } +} diff --git a/packages/server/src/handler.js b/packages/server/src/handler.js index 5f1bcbf3..74999be3 100644 --- a/packages/server/src/handler.js +++ b/packages/server/src/handler.js @@ -1,5 +1,5 @@ import * as API from './api.js' -import { access } from '@ucanto/validator' +import { access } from '@ucanto/core/validator' /** * @template {API.Ability} A diff --git a/packages/server/src/server.js b/packages/server/src/server.js index 6f5b3d6a..37ffbeda 100644 --- a/packages/server/src/server.js +++ b/packages/server/src/server.js @@ -1,13 +1,12 @@ import * as API from '@ucanto/interface' -import { InvalidAudience } from '@ucanto/validator' import { Verifier } from '@ucanto/principal' +import { InvalidAudience } from '@ucanto/core/validator' +export { capability, Schema } from '@ucanto/core' export { - capability, - URI, - Link, Failure, MalformedCapability, -} from '@ucanto/validator' + InvalidAudience, +} from '@ucanto/core/validator' /** * Creates a connection to a service. diff --git a/packages/server/test/handler.spec.js b/packages/server/test/handler.spec.js index 62606a35..fb5255a1 100644 --- a/packages/server/test/handler.spec.js +++ b/packages/server/test/handler.spec.js @@ -7,7 +7,6 @@ import { alice, bob, mallory, service as w3 } from './fixtures.js' import { test, assert } from './test.js' import * as Access from './service/access.js' import { Verifier } from '@ucanto/principal/ed25519' -import { UnavailableProof } from '@ucanto/validator' const context = { id: w3, @@ -20,10 +19,6 @@ const context = { canIssue: (capability, issuer) => capability.with === issuer || issuer == w3.did(), principal: Verifier, - /** - * @param {API.UCANLink} link - */ - resolve: link => new UnavailableProof(link), } test('invocation', async () => { diff --git a/packages/server/test/server.spec.js b/packages/server/test/server.spec.js index b2bd53cb..30e395aa 100644 --- a/packages/server/test/server.spec.js +++ b/packages/server/test/server.spec.js @@ -8,9 +8,9 @@ import { test, assert } from './test.js' const storeAdd = Server.capability({ can: 'store/add', - with: Server.URI.match({ protocol: 'did:' }), + with: Server.Schema.URI.match({ protocol: 'did:' }), nb: { - link: Server.Link.match().optional(), + link: Server.Schema.Link.match().optional(), }, derives: (claimed, delegated) => { if (claimed.with !== delegated.with) { @@ -33,9 +33,9 @@ const storeAdd = Server.capability({ }) const storeRemove = Server.capability({ can: 'store/remove', - with: Server.URI.match({ protocol: 'did:' }), + with: Server.Schema.URI.match({ protocol: 'did:' }), nb: { - link: Server.Link.match().optional(), + link: Server.Schema.Link.match().optional(), }, derives: (claimed, delegated) => { if (claimed.with !== delegated.with) { diff --git a/packages/server/test/service/access.js b/packages/server/test/service/access.js index a245127b..1afac82b 100644 --- a/packages/server/test/service/access.js +++ b/packages/server/test/service/access.js @@ -6,7 +6,7 @@ export const id = w3 const registerCapability = Server.capability({ can: 'identity/register', - with: Server.URI.match({ protocol: 'mailto:' }), + with: Server.Schema.URI.match({ protocol: 'mailto:' }), derives: (claimed, delegated) => claimed.with === delegated.with || new Server.Failure( @@ -16,7 +16,7 @@ const registerCapability = Server.capability({ const linkCapability = Server.capability({ can: 'identity/link', - with: Server.URI, + with: Server.Schema.URI, derives: (claimed, delegated) => claimed.with === delegated.with || new Server.Failure( @@ -26,7 +26,7 @@ const linkCapability = Server.capability({ const identifyCapability = Server.capability({ can: 'identity/identify', - with: Server.URI, + with: Server.Schema.URI, derives: (claimed, delegated) => claimed.with === delegated.with || delegated.with === 'ucan:*' || diff --git a/packages/server/test/service/store.js b/packages/server/test/service/store.js index 75f8c5d4..da78bb37 100644 --- a/packages/server/test/service/store.js +++ b/packages/server/test/service/store.js @@ -7,9 +7,9 @@ import { service as issuer } from '../fixtures.js' const addCapability = Server.capability({ can: 'store/add', - with: Server.URI.match({ protocol: 'did:' }), + with: Server.Schema.URI.match({ protocol: 'did:' }), nb: { - link: Server.Link.match().optional(), + link: Server.Schema.Link.match().optional(), }, derives: (claimed, delegated) => { if (claimed.with !== delegated.with) { @@ -33,9 +33,9 @@ const addCapability = Server.capability({ const removeCapability = Server.capability({ can: 'store/remove', - with: Server.URI.match({ protocol: 'did:' }), + with: Server.Schema.URI.match({ protocol: 'did:' }), nb: { - link: Server.Link.match().optional(), + link: Server.Schema.Link.match().optional(), }, derives: (claimed, delegated) => { if (claimed.with !== delegated.with) { diff --git a/packages/server/tsconfig.json b/packages/server/tsconfig.json index 3e549c1a..88b09a3f 100644 --- a/packages/server/tsconfig.json +++ b/packages/server/tsconfig.json @@ -103,7 +103,6 @@ { "path": "../interface" }, { "path": "../core" }, { "path": "../transport" }, - { "path": "../client" }, - { "path": "../validator" } + { "path": "../client" } ] } diff --git a/packages/validator/CHANGELOG.md b/packages/validator/CHANGELOG.md deleted file mode 100644 index c1c96d7e..00000000 --- a/packages/validator/CHANGELOG.md +++ /dev/null @@ -1,612 +0,0 @@ -# Changelog - -## [4.1.0](https://www.github.com/web3-storage/ucanto/compare/validator-v4.0.3...validator-v4.1.0) (2023-01-24) - - -### Features - -* implement dictionary schema ([#192](https://www.github.com/web3-storage/ucanto/issues/192)) ([a872395](https://www.github.com/web3-storage/ucanto/commit/a8723950a42636b5da658c4e8272a46a7a899e6d)) -* update multiformats ([#197](https://www.github.com/web3-storage/ucanto/issues/197)) ([b92a6c6](https://www.github.com/web3-storage/ucanto/commit/b92a6c6f5c066890a25e62205ff9848b1fb8dde1)) - - -### Bug Fixes - -* error messages on invalid proofs ([#187](https://www.github.com/web3-storage/ucanto/issues/187)) ([cb1a3bc](https://www.github.com/web3-storage/ucanto/commit/cb1a3bca9d51c95f369f28f1c2be46ee213ed053)) - -## [4.1.0](https://www.github.com/web3-storage/ucanto/compare/validator-v4.0.3...validator-v4.1.0) (2023-01-18) - - -### Features - -* implement dictionary schema ([#192](https://www.github.com/web3-storage/ucanto/issues/192)) ([a872395](https://www.github.com/web3-storage/ucanto/commit/a8723950a42636b5da658c4e8272a46a7a899e6d)) -* update multiformats ([#197](https://www.github.com/web3-storage/ucanto/issues/197)) ([b92a6c6](https://www.github.com/web3-storage/ucanto/commit/b92a6c6f5c066890a25e62205ff9848b1fb8dde1)) - - -### Bug Fixes - -* error messages on invalid proofs ([#187](https://www.github.com/web3-storage/ucanto/issues/187)) ([cb1a3bc](https://www.github.com/web3-storage/ucanto/commit/cb1a3bca9d51c95f369f28f1c2be46ee213ed053)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^4.0.3 to ^4.1.0 - * @ucanto/interface bumped from ^4.0.3 to ^4.1.0 - * devDependencies - * @ucanto/client bumped from ^4.0.3 to ^4.1.0 - * @ucanto/principal bumped from ^4.0.3 to ^4.1.0 - -### [4.0.3](https://www.github.com/web3-storage/ucanto/compare/validator-v4.0.2...validator-v4.0.3) (2022-12-14) - - -### Bug Fixes - -* trigger releases ([a0d9291](https://www.github.com/web3-storage/ucanto/commit/a0d9291f9e20456e115fa6c7890cafe937fa511e)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^4.0.2 to ^4.0.3 - * @ucanto/interface bumped from ^4.0.2 to ^4.0.3 - * devDependencies - * @ucanto/client bumped from ^4.0.2 to ^4.0.3 - * @ucanto/principal bumped from ^4.0.2 to ^4.0.3 - -## [4.0.2](https://github.com/web3-storage/ucanto/compare/validator-v4.1.0...validator-v4.0.2) (2022-12-14) - -### ⚠ BREAKING CHANGES - -* upgrades to multiformats@10 ([#117](https://github.com/web3-storage/ucanto/issues/117)) -* switch decoder API to zod like schema API ([#108](https://github.com/web3-storage/ucanto/issues/108)) -* upgrade to ucan 0.9 ([#95](https://github.com/web3-storage/ucanto/issues/95)) -* update dag-ucan, types and names ([#90](https://github.com/web3-storage/ucanto/issues/90)) - -### Features - -* alight link API with multiformats ([#36](https://github.com/web3-storage/ucanto/issues/36)) ([0ec460e](https://github.com/web3-storage/ucanto/commit/0ec460e43ddda0bb3a3fea8a7881da1463154f36)) -* capability provider API ([#34](https://github.com/web3-storage/ucanto/issues/34)) ([ea89f97](https://github.com/web3-storage/ucanto/commit/ea89f97125bb484a12ce3ca09a7884911a9fd4d6)) -* cherry pick changes from uploads-v2 demo ([#43](https://github.com/web3-storage/ucanto/issues/43)) ([4308fd2](https://github.com/web3-storage/ucanto/commit/4308fd2f392b9fcccc52af64432dcb04c8257e0b)) -* delgation iterate, more errors and types ([0606168](https://github.com/web3-storage/ucanto/commit/0606168313d17d66bcc1ad6091440765e1700a4f)) -* embedded key resolution ([#168](https://github.com/web3-storage/ucanto/issues/168)) ([5e650f3](https://github.com/web3-storage/ucanto/commit/5e650f376db79c690e4771695d1ff4e6deece40e)) -* Impelment InferInvokedCapability per [#99](https://github.com/web3-storage/ucanto/issues/99) ([#100](https://github.com/web3-storage/ucanto/issues/100)) ([fc5a2ac](https://github.com/web3-storage/ucanto/commit/fc5a2ace33f2a3599a654d8edd1641d111032074)) -* implement .delegate on capabilities ([#110](https://github.com/web3-storage/ucanto/issues/110)) ([fd0bb9d](https://github.com/web3-storage/ucanto/commit/fd0bb9da58836c05d6ee9f60cd6b1cb6b747e3b1)) -* refactor into monorepo ([#13](https://github.com/web3-storage/ucanto/issues/13)) ([1f99506](https://github.com/web3-storage/ucanto/commit/1f995064ec6e5953118c2dd1065ee6be959f25b9)) -* rip out special handling of my: and as: capabilities ([#109](https://github.com/web3-storage/ucanto/issues/109)) ([3ec8e64](https://github.com/web3-storage/ucanto/commit/3ec8e6434a096221bf72193e074810cc18dd5cd8)) -* setup pnpm & release-please ([84ac7f1](https://github.com/web3-storage/ucanto/commit/84ac7f12e5a66ee4919fa7527858dc916850e3e0)) -* switch decoder API to zod like schema API ([#108](https://github.com/web3-storage/ucanto/issues/108)) ([e2e03ff](https://github.com/web3-storage/ucanto/commit/e2e03ffeb35f00627335dbfd3e128e2cf9dcfdee)) -* **ucanto:** capability create / inovke methods ([#51](https://github.com/web3-storage/ucanto/issues/51)) ([ddf56b1](https://github.com/web3-storage/ucanto/commit/ddf56b1ec80ff6c0698255c531936d8eeab532fd)) -* **ucanto:** URI protocol type retention & capability constructors ([e291544](https://github.com/web3-storage/ucanto/commit/e2915447254990d6e2384ff79a1da38120426ed5)) -* update dag-ucan, types and names ([#90](https://github.com/web3-storage/ucanto/issues/90)) ([cd792c9](https://github.com/web3-storage/ucanto/commit/cd792c934fbd358d6ccfa5d02f205b14b5f2e14e)) -* upgrade to ucan 0.9 ([#95](https://github.com/web3-storage/ucanto/issues/95)) ([b752b39](https://github.com/web3-storage/ucanto/commit/b752b398950120d6121badcdbb639f4dc9ce8794)) -* upgrades to multiformats@10 ([#117](https://github.com/web3-storage/ucanto/issues/117)) ([61dc4ca](https://github.com/web3-storage/ucanto/commit/61dc4cafece3365bbf60f709265ea71180f226d7)) - - -### Bug Fixes - -* add return type to URI.uri() schema ([#127](https://github.com/web3-storage/ucanto/issues/127)) ([c302866](https://github.com/web3-storage/ucanto/commit/c3028667bc1094e6f6b16c43b3a396ef6207f75c)) -* build types before publishing ([#71](https://github.com/web3-storage/ucanto/issues/71)) ([04b7958](https://github.com/web3-storage/ucanto/commit/04b79588f77dba234aaf628f62f574b124bd540b)) -* downgrade versions ([#158](https://github.com/web3-storage/ucanto/issues/158)) ([f814e75](https://github.com/web3-storage/ucanto/commit/f814e75a89d3ed7c3488a8cb7af8d94f0cfba440)) -* intermittent test failures ([#166](https://github.com/web3-storage/ucanto/issues/166)) ([6cb0348](https://github.com/web3-storage/ucanto/commit/6cb03482bd257d2ea62b6558e1f6ee1a693b68fb)) -* optional caveats ([#106](https://github.com/web3-storage/ucanto/issues/106)) ([537a4c8](https://github.com/web3-storage/ucanto/commit/537a4c86fdd02c26c1442d6a205e8977afbad603)) -* optional field validation ([#124](https://github.com/web3-storage/ucanto/issues/124)) ([87b70d2](https://github.com/web3-storage/ucanto/commit/87b70d2d56c07f8257717fa5ef584a21eb0417c8)) -* package scripts to build types ([#84](https://github.com/web3-storage/ucanto/issues/84)) ([4d21132](https://github.com/web3-storage/ucanto/commit/4d2113246abdda215dd3fa882730ba71e68b5695)) -* update @ipld/car and @ipld/dag-cbor deps ([#120](https://github.com/web3-storage/ucanto/issues/120)) ([5dcd7a5](https://github.com/web3-storage/ucanto/commit/5dcd7a5788dfd126f332b126f7ad1215972f29c4)) -* versions ([#131](https://github.com/web3-storage/ucanto/issues/131)) ([88b87a7](https://github.com/web3-storage/ucanto/commit/88b87a7f3a32c02a22ddffcb8f38199445097133)) - - -### Miscellaneous Chores - -* release 0.0.1-beta ([d6c7e73](https://github.com/web3-storage/ucanto/commit/d6c7e73de56278e2f2c92c4a0e1a2709c92bcbf9)) -* release 4.0.2 ([e9e35df](https://github.com/web3-storage/ucanto/commit/e9e35dffeeb7e5b5e19627f791b66bbdd35d2d11)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^4.0.3 to ^4.0.2 - * @ucanto/interface bumped from ^4.1.0 to ^4.0.2 - * devDependencies - * @ucanto/client bumped from ^4.0.3 to ^4.0.2 - * @ucanto/principal bumped from ^4.1.0 to ^4.0.2 - -## [4.1.0](https://github.com/web3-storage/ucanto/compare/validator-v4.0.2...validator-v4.1.0) (2022-12-14) - - -### Features - -* embedded key resolution ([#168](https://github.com/web3-storage/ucanto/issues/168)) ([5e650f3](https://github.com/web3-storage/ucanto/commit/5e650f376db79c690e4771695d1ff4e6deece40e)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^4.0.2 to ^4.0.3 - * @ucanto/interface bumped from ^4.0.2 to ^4.1.0 - * devDependencies - * @ucanto/client bumped from ^4.0.2 to ^4.0.3 - * @ucanto/principal bumped from ^4.0.2 to ^4.1.0 - -## [4.0.2](https://github.com/web3-storage/ucanto/compare/validator-v4.1.0...validator-v4.0.2) (2022-12-14) - - -### ⚠ BREAKING CHANGES - -* upgrades to multiformats@10 ([#117](https://github.com/web3-storage/ucanto/issues/117)) -* switch decoder API to zod like schema API ([#108](https://github.com/web3-storage/ucanto/issues/108)) -* upgrade to ucan 0.9 ([#95](https://github.com/web3-storage/ucanto/issues/95)) -* update dag-ucan, types and names ([#90](https://github.com/web3-storage/ucanto/issues/90)) - -### Features - -* alight link API with multiformats ([#36](https://github.com/web3-storage/ucanto/issues/36)) ([0ec460e](https://github.com/web3-storage/ucanto/commit/0ec460e43ddda0bb3a3fea8a7881da1463154f36)) -* capability provider API ([#34](https://github.com/web3-storage/ucanto/issues/34)) ([ea89f97](https://github.com/web3-storage/ucanto/commit/ea89f97125bb484a12ce3ca09a7884911a9fd4d6)) -* cherry pick changes from uploads-v2 demo ([#43](https://github.com/web3-storage/ucanto/issues/43)) ([4308fd2](https://github.com/web3-storage/ucanto/commit/4308fd2f392b9fcccc52af64432dcb04c8257e0b)) -* delgation iterate, more errors and types ([0606168](https://github.com/web3-storage/ucanto/commit/0606168313d17d66bcc1ad6091440765e1700a4f)) -* embedded key resolution ([#168](https://github.com/web3-storage/ucanto/issues/168)) ([5e650f3](https://github.com/web3-storage/ucanto/commit/5e650f376db79c690e4771695d1ff4e6deece40e)) -* Impelment InferInvokedCapability per [#99](https://github.com/web3-storage/ucanto/issues/99) ([#100](https://github.com/web3-storage/ucanto/issues/100)) ([fc5a2ac](https://github.com/web3-storage/ucanto/commit/fc5a2ace33f2a3599a654d8edd1641d111032074)) -* implement .delegate on capabilities ([#110](https://github.com/web3-storage/ucanto/issues/110)) ([fd0bb9d](https://github.com/web3-storage/ucanto/commit/fd0bb9da58836c05d6ee9f60cd6b1cb6b747e3b1)) -* refactor into monorepo ([#13](https://github.com/web3-storage/ucanto/issues/13)) ([1f99506](https://github.com/web3-storage/ucanto/commit/1f995064ec6e5953118c2dd1065ee6be959f25b9)) -* rip out special handling of my: and as: capabilities ([#109](https://github.com/web3-storage/ucanto/issues/109)) ([3ec8e64](https://github.com/web3-storage/ucanto/commit/3ec8e6434a096221bf72193e074810cc18dd5cd8)) -* setup pnpm & release-please ([84ac7f1](https://github.com/web3-storage/ucanto/commit/84ac7f12e5a66ee4919fa7527858dc916850e3e0)) -* switch decoder API to zod like schema API ([#108](https://github.com/web3-storage/ucanto/issues/108)) ([e2e03ff](https://github.com/web3-storage/ucanto/commit/e2e03ffeb35f00627335dbfd3e128e2cf9dcfdee)) -* **ucanto:** capability create / inovke methods ([#51](https://github.com/web3-storage/ucanto/issues/51)) ([ddf56b1](https://github.com/web3-storage/ucanto/commit/ddf56b1ec80ff6c0698255c531936d8eeab532fd)) -* **ucanto:** URI protocol type retention & capability constructors ([e291544](https://github.com/web3-storage/ucanto/commit/e2915447254990d6e2384ff79a1da38120426ed5)) -* update dag-ucan, types and names ([#90](https://github.com/web3-storage/ucanto/issues/90)) ([cd792c9](https://github.com/web3-storage/ucanto/commit/cd792c934fbd358d6ccfa5d02f205b14b5f2e14e)) -* upgrade to ucan 0.9 ([#95](https://github.com/web3-storage/ucanto/issues/95)) ([b752b39](https://github.com/web3-storage/ucanto/commit/b752b398950120d6121badcdbb639f4dc9ce8794)) -* upgrades to multiformats@10 ([#117](https://github.com/web3-storage/ucanto/issues/117)) ([61dc4ca](https://github.com/web3-storage/ucanto/commit/61dc4cafece3365bbf60f709265ea71180f226d7)) - - -### Bug Fixes - -* add return type to URI.uri() schema ([#127](https://github.com/web3-storage/ucanto/issues/127)) ([c302866](https://github.com/web3-storage/ucanto/commit/c3028667bc1094e6f6b16c43b3a396ef6207f75c)) -* build types before publishing ([#71](https://github.com/web3-storage/ucanto/issues/71)) ([04b7958](https://github.com/web3-storage/ucanto/commit/04b79588f77dba234aaf628f62f574b124bd540b)) -* downgrade versions ([#158](https://github.com/web3-storage/ucanto/issues/158)) ([f814e75](https://github.com/web3-storage/ucanto/commit/f814e75a89d3ed7c3488a8cb7af8d94f0cfba440)) -* intermittent test failures ([#166](https://github.com/web3-storage/ucanto/issues/166)) ([6cb0348](https://github.com/web3-storage/ucanto/commit/6cb03482bd257d2ea62b6558e1f6ee1a693b68fb)) -* optional caveats ([#106](https://github.com/web3-storage/ucanto/issues/106)) ([537a4c8](https://github.com/web3-storage/ucanto/commit/537a4c86fdd02c26c1442d6a205e8977afbad603)) -* optional field validation ([#124](https://github.com/web3-storage/ucanto/issues/124)) ([87b70d2](https://github.com/web3-storage/ucanto/commit/87b70d2d56c07f8257717fa5ef584a21eb0417c8)) -* package scripts to build types ([#84](https://github.com/web3-storage/ucanto/issues/84)) ([4d21132](https://github.com/web3-storage/ucanto/commit/4d2113246abdda215dd3fa882730ba71e68b5695)) -* update @ipld/car and @ipld/dag-cbor deps ([#120](https://github.com/web3-storage/ucanto/issues/120)) ([5dcd7a5](https://github.com/web3-storage/ucanto/commit/5dcd7a5788dfd126f332b126f7ad1215972f29c4)) -* versions ([#131](https://github.com/web3-storage/ucanto/issues/131)) ([88b87a7](https://github.com/web3-storage/ucanto/commit/88b87a7f3a32c02a22ddffcb8f38199445097133)) - - -### Miscellaneous Chores - -* release 0.0.1-beta ([d6c7e73](https://github.com/web3-storage/ucanto/commit/d6c7e73de56278e2f2c92c4a0e1a2709c92bcbf9)) -* release 4.0.2 ([e9e35df](https://github.com/web3-storage/ucanto/commit/e9e35dffeeb7e5b5e19627f791b66bbdd35d2d11)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^4.0.3 to ^4.0.2 - * @ucanto/interface bumped from ^4.1.0 to ^4.0.2 - * devDependencies - * @ucanto/client bumped from ^4.0.3 to ^4.0.2 - * @ucanto/principal bumped from ^4.1.0 to ^4.0.2 - -## [4.1.0](https://github.com/web3-storage/ucanto/compare/validator-v4.0.2...validator-v4.1.0) (2022-12-14) - - -### Features - -* embedded key resolution ([#168](https://github.com/web3-storage/ucanto/issues/168)) ([5e650f3](https://github.com/web3-storage/ucanto/commit/5e650f376db79c690e4771695d1ff4e6deece40e)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^4.0.2 to ^4.0.3 - * @ucanto/interface bumped from ^4.0.2 to ^4.1.0 - * devDependencies - * @ucanto/client bumped from ^4.0.2 to ^4.0.3 - * @ucanto/principal bumped from ^4.0.2 to ^4.1.0 - -## [4.0.2](https://github.com/web3-storage/ucanto/compare/validator-v4.0.2...validator-v4.0.2) (2022-12-02) - - -### ⚠ BREAKING CHANGES - -* upgrades to multiformats@10 (#117) -* switch decoder API to zod like schema API (#108) -* upgrade to ucan 0.9 (#95) -* update dag-ucan, types and names (#90) - -### Features - -* alight link API with multiformats ([#36](https://github.com/web3-storage/ucanto/issues/36)) ([0ec460e](https://github.com/web3-storage/ucanto/commit/0ec460e43ddda0bb3a3fea8a7881da1463154f36)) -* capability provider API ([#34](https://github.com/web3-storage/ucanto/issues/34)) ([ea89f97](https://github.com/web3-storage/ucanto/commit/ea89f97125bb484a12ce3ca09a7884911a9fd4d6)) -* cherry pick changes from uploads-v2 demo ([#43](https://github.com/web3-storage/ucanto/issues/43)) ([4308fd2](https://github.com/web3-storage/ucanto/commit/4308fd2f392b9fcccc52af64432dcb04c8257e0b)) -* delgation iterate, more errors and types ([0606168](https://github.com/web3-storage/ucanto/commit/0606168313d17d66bcc1ad6091440765e1700a4f)) -* Impelment InferInvokedCapability per [#99](https://github.com/web3-storage/ucanto/issues/99) ([#100](https://github.com/web3-storage/ucanto/issues/100)) ([fc5a2ac](https://github.com/web3-storage/ucanto/commit/fc5a2ace33f2a3599a654d8edd1641d111032074)) -* implement .delegate on capabilities ([#110](https://github.com/web3-storage/ucanto/issues/110)) ([fd0bb9d](https://github.com/web3-storage/ucanto/commit/fd0bb9da58836c05d6ee9f60cd6b1cb6b747e3b1)) -* rip out special handling of my: and as: capabilities ([#109](https://github.com/web3-storage/ucanto/issues/109)) ([3ec8e64](https://github.com/web3-storage/ucanto/commit/3ec8e6434a096221bf72193e074810cc18dd5cd8)) -* setup pnpm & release-please ([84ac7f1](https://github.com/web3-storage/ucanto/commit/84ac7f12e5a66ee4919fa7527858dc916850e3e0)) -* switch decoder API to zod like schema API ([#108](https://github.com/web3-storage/ucanto/issues/108)) ([e2e03ff](https://github.com/web3-storage/ucanto/commit/e2e03ffeb35f00627335dbfd3e128e2cf9dcfdee)) -* **ucanto:** capability create / inovke methods ([#51](https://github.com/web3-storage/ucanto/issues/51)) ([ddf56b1](https://github.com/web3-storage/ucanto/commit/ddf56b1ec80ff6c0698255c531936d8eeab532fd)) -* **ucanto:** URI protocol type retention & capability constructors ([e291544](https://github.com/web3-storage/ucanto/commit/e2915447254990d6e2384ff79a1da38120426ed5)) -* update dag-ucan, types and names ([#90](https://github.com/web3-storage/ucanto/issues/90)) ([cd792c9](https://github.com/web3-storage/ucanto/commit/cd792c934fbd358d6ccfa5d02f205b14b5f2e14e)) -* upgrade to ucan 0.9 ([#95](https://github.com/web3-storage/ucanto/issues/95)) ([b752b39](https://github.com/web3-storage/ucanto/commit/b752b398950120d6121badcdbb639f4dc9ce8794)) -* upgrades to multiformats@10 ([#117](https://github.com/web3-storage/ucanto/issues/117)) ([61dc4ca](https://github.com/web3-storage/ucanto/commit/61dc4cafece3365bbf60f709265ea71180f226d7)) - - -### Bug Fixes - -* add return type to URI.uri() schema ([#127](https://github.com/web3-storage/ucanto/issues/127)) ([c302866](https://github.com/web3-storage/ucanto/commit/c3028667bc1094e6f6b16c43b3a396ef6207f75c)) -* build types before publishing ([#71](https://github.com/web3-storage/ucanto/issues/71)) ([04b7958](https://github.com/web3-storage/ucanto/commit/04b79588f77dba234aaf628f62f574b124bd540b)) -* downgrade versions ([#158](https://github.com/web3-storage/ucanto/issues/158)) ([f814e75](https://github.com/web3-storage/ucanto/commit/f814e75a89d3ed7c3488a8cb7af8d94f0cfba440)) -* intermittent test failures ([#166](https://github.com/web3-storage/ucanto/issues/166)) ([6cb0348](https://github.com/web3-storage/ucanto/commit/6cb03482bd257d2ea62b6558e1f6ee1a693b68fb)) -* optional caveats ([#106](https://github.com/web3-storage/ucanto/issues/106)) ([537a4c8](https://github.com/web3-storage/ucanto/commit/537a4c86fdd02c26c1442d6a205e8977afbad603)) -* optional field validation ([#124](https://github.com/web3-storage/ucanto/issues/124)) ([87b70d2](https://github.com/web3-storage/ucanto/commit/87b70d2d56c07f8257717fa5ef584a21eb0417c8)) -* package scripts to build types ([#84](https://github.com/web3-storage/ucanto/issues/84)) ([4d21132](https://github.com/web3-storage/ucanto/commit/4d2113246abdda215dd3fa882730ba71e68b5695)) -* update @ipld/car and @ipld/dag-cbor deps ([#120](https://github.com/web3-storage/ucanto/issues/120)) ([5dcd7a5](https://github.com/web3-storage/ucanto/commit/5dcd7a5788dfd126f332b126f7ad1215972f29c4)) -* versions ([#131](https://github.com/web3-storage/ucanto/issues/131)) ([88b87a7](https://github.com/web3-storage/ucanto/commit/88b87a7f3a32c02a22ddffcb8f38199445097133)) - - -### Miscellaneous Chores - -* release 4.0.2 ([e9e35df](https://github.com/web3-storage/ucanto/commit/e9e35dffeeb7e5b5e19627f791b66bbdd35d2d11)) - -## [4.0.2](https://github.com/web3-storage/ucanto/compare/validator-v3.0.7...validator-v4.0.2) (2022-12-02) - - -### Bug Fixes - -* intermittent test failures ([#166](https://github.com/web3-storage/ucanto/issues/166)) ([6cb0348](https://github.com/web3-storage/ucanto/commit/6cb03482bd257d2ea62b6558e1f6ee1a693b68fb)) - - -### Miscellaneous Chores - -* release 4.0.2 ([e9e35df](https://github.com/web3-storage/ucanto/commit/e9e35dffeeb7e5b5e19627f791b66bbdd35d2d11)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^4.0.0 to ^4.0.2 - * @ucanto/interface bumped from ^4.0.0 to ^4.0.2 - * devDependencies - * @ucanto/client bumped from ^4.0.0 to ^4.0.2 - * @ucanto/principal bumped from ^4.0.1 to ^4.0.2 - -### [3.0.7](https://www.github.com/web3-storage/ucanto/compare/validator-v3.0.6...validator-v3.0.7) (2022-12-02) - - -### Bug Fixes - -* downgrade versions ([#158](https://www.github.com/web3-storage/ucanto/issues/158)) ([f814e75](https://www.github.com/web3-storage/ucanto/commit/f814e75a89d3ed7c3488a8cb7af8d94f0cfba440)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^3.0.4 to ^3.0.5 - * devDependencies - * @ucanto/client bumped from ^3.0.4 to ^3.0.5 - -### [3.0.6](https://www.github.com/web3-storage/ucanto/compare/validator-v3.0.5...validator-v3.0.6) (2022-12-02) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^3.0.3 to ^3.0.4 - * devDependencies - * @ucanto/client bumped from ^3.0.3 to ^3.0.4 - * @ucanto/principal bumped from ^4.0.0 to ^4.0.1 - -### [3.0.5](https://www.github.com/web3-storage/ucanto/compare/validator-v3.0.4...validator-v3.0.5) (2022-12-01) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^3.0.2 to ^3.0.3 - * @ucanto/interface bumped from ^3.0.1 to ^4.0.0 - * devDependencies - * @ucanto/client bumped from ^3.0.2 to ^3.0.3 - * @ucanto/principal bumped from ^3.0.1 to ^4.0.0 - -### [3.0.4](https://www.github.com/web3-storage/ucanto/compare/validator-v3.0.3...validator-v3.0.4) (2022-11-12) - - -### Bug Fixes - -* versions ([#131](https://www.github.com/web3-storage/ucanto/issues/131)) ([88b87a7](https://www.github.com/web3-storage/ucanto/commit/88b87a7f3a32c02a22ddffcb8f38199445097133)) - -### [3.0.3](https://www.github.com/web3-storage/ucanto/compare/validator-v3.0.2...validator-v3.0.3) (2022-11-12) - - -### Bug Fixes - -* add return type to URI.uri() schema ([#127](https://www.github.com/web3-storage/ucanto/issues/127)) ([c302866](https://www.github.com/web3-storage/ucanto/commit/c3028667bc1094e6f6b16c43b3a396ef6207f75c)) - -### [3.0.2](https://www.github.com/web3-storage/ucanto/compare/validator-v3.0.1...validator-v3.0.2) (2022-11-11) - - -### Bug Fixes - -* optional field validation ([#124](https://www.github.com/web3-storage/ucanto/issues/124)) ([87b70d2](https://www.github.com/web3-storage/ucanto/commit/87b70d2d56c07f8257717fa5ef584a21eb0417c8)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^3.0.1 to ^3.0.2 - * @ucanto/interface bumped from ^3.0.0 to ^3.0.1 - * devDependencies - * @ucanto/client bumped from ^3.0.1 to ^3.0.2 - * @ucanto/principal bumped from ^3.0.0 to ^3.0.1 - -### [3.0.1](https://www.github.com/web3-storage/ucanto/compare/validator-v3.0.0...validator-v3.0.1) (2022-11-02) - - -### Bug Fixes - -* update @ipld/car and @ipld/dag-cbor deps ([#120](https://www.github.com/web3-storage/ucanto/issues/120)) ([5dcd7a5](https://www.github.com/web3-storage/ucanto/commit/5dcd7a5788dfd126f332b126f7ad1215972f29c4)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^3.0.0 to ^3.0.1 - * devDependencies - * @ucanto/client bumped from ^3.0.0 to ^3.0.1 - -## [3.0.0](https://www.github.com/web3-storage/ucanto/compare/validator-v2.0.0...validator-v3.0.0) (2022-10-20) - - -### ⚠ BREAKING CHANGES - -* upgrades to multiformats@10 (#117) - -### Features - -* upgrades to multiformats@10 ([#117](https://www.github.com/web3-storage/ucanto/issues/117)) ([61dc4ca](https://www.github.com/web3-storage/ucanto/commit/61dc4cafece3365bbf60f709265ea71180f226d7)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^2.0.0 to ^3.0.0 - * @ucanto/interface bumped from ^2.0.0 to ^3.0.0 - * devDependencies - * @ucanto/principal bumped from ^2.0.0 to ^3.0.0 - * @ucanto/client bumped from ^2.0.0 to ^3.0.0 - -## [2.0.0](https://www.github.com/web3-storage/ucanto/compare/validator-v1.0.1...validator-v2.0.0) (2022-10-16) - - -### ⚠ BREAKING CHANGES - -* switch decoder API to zod like schema API (#108) -* upgrade to ucan 0.9 (#95) - -### Features - -* Impelment InferInvokedCapability per [#99](https://www.github.com/web3-storage/ucanto/issues/99) ([#100](https://www.github.com/web3-storage/ucanto/issues/100)) ([fc5a2ac](https://www.github.com/web3-storage/ucanto/commit/fc5a2ace33f2a3599a654d8edd1641d111032074)) -* implement .delegate on capabilities ([#110](https://www.github.com/web3-storage/ucanto/issues/110)) ([fd0bb9d](https://www.github.com/web3-storage/ucanto/commit/fd0bb9da58836c05d6ee9f60cd6b1cb6b747e3b1)) -* rip out special handling of my: and as: capabilities ([#109](https://www.github.com/web3-storage/ucanto/issues/109)) ([3ec8e64](https://www.github.com/web3-storage/ucanto/commit/3ec8e6434a096221bf72193e074810cc18dd5cd8)) -* switch decoder API to zod like schema API ([#108](https://www.github.com/web3-storage/ucanto/issues/108)) ([e2e03ff](https://www.github.com/web3-storage/ucanto/commit/e2e03ffeb35f00627335dbfd3e128e2cf9dcfdee)) -* upgrade to ucan 0.9 ([#95](https://www.github.com/web3-storage/ucanto/issues/95)) ([b752b39](https://www.github.com/web3-storage/ucanto/commit/b752b398950120d6121badcdbb639f4dc9ce8794)) - - -### Bug Fixes - -* optional caveats ([#106](https://www.github.com/web3-storage/ucanto/issues/106)) ([537a4c8](https://www.github.com/web3-storage/ucanto/commit/537a4c86fdd02c26c1442d6a205e8977afbad603)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^1.0.1 to ^2.0.0 - * @ucanto/interface bumped from ^1.0.0 to ^2.0.0 - * devDependencies - * @ucanto/principal bumped from ^1.0.1 to ^2.0.0 - * @ucanto/client bumped from ^1.0.1 to ^2.0.0 - -### [1.0.1](https://www.github.com/web3-storage/ucanto/compare/validator-v1.0.0...validator-v1.0.1) (2022-09-21) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^1.0.0 to ^1.0.1 - * devDependencies - * @ucanto/principal bumped from ^1.0.0 to ^1.0.1 - * @ucanto/client bumped from ^1.0.0 to ^1.0.1 - -## [1.0.0](https://www.github.com/web3-storage/ucanto/compare/validator-v0.6.0...validator-v1.0.0) (2022-09-14) - - -### ⚠ BREAKING CHANGES - -* update dag-ucan, types and names (#90) - -### Features - -* update dag-ucan, types and names ([#90](https://www.github.com/web3-storage/ucanto/issues/90)) ([cd792c9](https://www.github.com/web3-storage/ucanto/commit/cd792c934fbd358d6ccfa5d02f205b14b5f2e14e)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.6.0 to ^1.0.0 - * @ucanto/interface bumped from ^0.7.0 to ^1.0.0 - * devDependencies - * @ucanto/principal bumped from ^0.5.0 to ^1.0.0 - * @ucanto/client bumped from ^0.6.0 to ^1.0.0 - -## [0.6.0](https://www.github.com/web3-storage/ucanto/compare/validator-v0.5.5...validator-v0.6.0) (2022-07-28) - - -### Features - -* delgation iterate, more errors and types ([0606168](https://www.github.com/web3-storage/ucanto/commit/0606168313d17d66bcc1ad6091440765e1700a4f)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.5.4 to ^0.6.0 - * @ucanto/interface bumped from ^0.6.2 to ^0.7.0 - * devDependencies - * @ucanto/authority bumped from ^0.4.5 to ^0.5.0 - * @ucanto/client bumped from ^0.5.4 to ^0.6.0 - -### [0.5.5](https://www.github.com/web3-storage/ucanto/compare/validator-v0.5.4...validator-v0.5.5) (2022-07-11) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.5.3 to ^0.5.4 - * devDependencies - * @ucanto/client bumped from ^0.5.3 to ^0.5.4 - * @ucanto/authority bumped from ^0.4.4 to ^0.4.5 - -### [0.5.4](https://www.github.com/web3-storage/ucanto/compare/validator-v0.5.3...validator-v0.5.4) (2022-07-01) - - -### Dependencies - -* The following workspace dependencies were updated - * devDependencies - * @ucanto/client bumped from ^0.5.2 to ^0.5.3 - -### [0.5.3](https://www.github.com/web3-storage/ucanto/compare/validator-v0.5.2...validator-v0.5.3) (2022-07-01) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.5.2 to ^0.5.3 - * @ucanto/interface bumped from ^0.6.1 to ^0.6.2 - * devDependencies - * @ucanto/client bumped from ^0.5.1 to ^0.5.2 - * @ucanto/authority bumped from ^0.4.3 to ^0.4.4 - -### [0.5.2](https://www.github.com/web3-storage/ucanto/compare/validator-v0.5.1...validator-v0.5.2) (2022-06-30) - - -### Bug Fixes - -* build types before publishing ([#71](https://www.github.com/web3-storage/ucanto/issues/71)) ([04b7958](https://www.github.com/web3-storage/ucanto/commit/04b79588f77dba234aaf628f62f574b124bd540b)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.5.1 to ^0.5.2 - * @ucanto/interface bumped from ^0.6.0 to ^0.6.1 - * devDependencies - * @ucanto/client bumped from ^0.5.0 to ^0.5.1 - * @ucanto/authority bumped from ^0.4.2 to ^0.4.3 - -### [0.5.1](https://www.github.com/web3-storage/ucanto/compare/validator-v0.5.0...validator-v0.5.1) (2022-06-24) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.5.0 to ^0.5.1 - * @ucanto/interface bumped from ^0.5.0 to ^0.6.0 - * devDependencies - * @ucanto/client bumped from ^0.4.0 to ^0.5.0 - * @ucanto/authority bumped from ^0.4.1 to ^0.4.2 - -## [0.5.0](https://www.github.com/web3-storage/ucanto/compare/validator-v0.4.0...validator-v0.5.0) (2022-06-23) - - -### Features - -* **ucanto:** capability create / inovke methods ([#51](https://www.github.com/web3-storage/ucanto/issues/51)) ([ddf56b1](https://www.github.com/web3-storage/ucanto/commit/ddf56b1ec80ff6c0698255c531936d8eeab532fd)) -* **ucanto:** URI protocol type retention & capability constructors ([e291544](https://www.github.com/web3-storage/ucanto/commit/e2915447254990d6e2384ff79a1da38120426ed5)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.4.0 to ^0.5.0 - * @ucanto/interface bumped from ^0.4.0 to ^0.5.0 - * devDependencies - * @ucanto/client bumped from ^0.3.0 to ^0.4.0 - * @ucanto/authority bumped from ^0.4.0 to ^0.4.1 - -## [0.4.0](https://www.github.com/web3-storage/ucanto/compare/validator-v0.3.0...validator-v0.4.0) (2022-06-20) - - -### Features - -* alight link API with multiformats ([#36](https://www.github.com/web3-storage/ucanto/issues/36)) ([0ec460e](https://www.github.com/web3-storage/ucanto/commit/0ec460e43ddda0bb3a3fea8a7881da1463154f36)) -* cherry pick changes from uploads-v2 demo ([#43](https://www.github.com/web3-storage/ucanto/issues/43)) ([4308fd2](https://www.github.com/web3-storage/ucanto/commit/4308fd2f392b9fcccc52af64432dcb04c8257e0b)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.3.0 to ^0.4.0 - * @ucanto/interface bumped from ^0.3.0 to ^0.4.0 - * devDependencies - * @ucanto/client bumped from ^0.2.2 to ^0.3.0 - * @ucanto/authority bumped from ^0.3.0 to ^0.4.0 - -## [0.3.0](https://www.github.com/web3-storage/ucanto/compare/validator-v0.2.0...validator-v0.3.0) (2022-06-15) - - -### Features - -* capability provider API ([#34](https://www.github.com/web3-storage/ucanto/issues/34)) ([ea89f97](https://www.github.com/web3-storage/ucanto/commit/ea89f97125bb484a12ce3ca09a7884911a9fd4d6)) - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.2.0 to ^0.3.0 - * @ucanto/interface bumped from ^0.2.0 to ^0.3.0 - * devDependencies - * @ucanto/client bumped from ^0.2.0 to ^0.2.2 - * @ucanto/authority bumped from ^0.2.0 to ^0.3.0 - -## [0.2.0](https://www.github.com/web3-storage/ucanto/compare/validator-v0.1.0...validator-v0.2.0) (2022-06-10) - - -### Features - -* setup pnpm & release-please ([84ac7f1](https://www.github.com/web3-storage/ucanto/commit/84ac7f12e5a66ee4919fa7527858dc916850e3e0)) - - - -### Dependencies - -* The following workspace dependencies were updated - * dependencies - * @ucanto/core bumped from ^0.0.1 to ^0.2.0 - * @ucanto/interface bumped from ^0.0.1 to ^0.2.0 - * devDependencies - * @ucanto/client bumped from ^0.0.1 to ^0.2.0 - * @ucanto/authority bumped from 0.0.1 to ^0.2.0 diff --git a/packages/validator/package.json b/packages/validator/package.json deleted file mode 100644 index 7ef33136..00000000 --- a/packages/validator/package.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "@ucanto/validator", - "description": "UCAN RPC validators", - "version": "4.1.0", - "keywords": [ - "UCAN", - "ed25519", - "did", - "issuer", - "audience" - ], - "files": [ - "src", - "dist/src" - ], - "repository": { - "type": "git", - "url": "https://github.com/web3-storage/ucanto.git" - }, - "homepage": "https://github.com/web3-storage/ucanto", - "scripts": { - "test:web": "playwright-test test/**/*.spec.js --cov && nyc report", - "test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/**/*.spec.js", - "test": "npm run test:node", - "coverage": "c8 --reporter=html mocha test/**/*.spec.js", - "check": "tsc --build", - "build": "tsc --build" - }, - "dependencies": { - "@ipld/car": "^5.0.3", - "@ipld/dag-cbor": "^8.0.0", - "@ucanto/core": "^4.1.0", - "@ucanto/interface": "^4.1.0", - "multiformats": "^11.0.0" - }, - "devDependencies": { - "@types/chai": "^4.3.3", - "@types/chai-subset": "^1.3.3", - "@types/mocha": "^9.1.0", - "@ucanto/client": "^4.1.0", - "@ucanto/principal": "^4.1.0", - "c8": "^7.11.0", - "chai": "^4.3.6", - "chai-subset": "^1.6.0", - "mocha": "^10.1.0", - "nyc": "^15.1.0", - "playwright-test": "^8.1.1", - "typescript": "^4.9.4" - }, - "type": "module", - "main": "src/lib.js", - "types": "./dist/src/lib.d.ts", - "typesVersions": { - "*": { - "*": [ - "dist/*" - ], - "dist/src/lib.d.ts": [ - "dist/src/lib.d.ts" - ] - } - }, - "exports": { - ".": { - "types": "./dist/src/lib.d.ts", - "import": "./src/lib.js" - } - }, - "c8": { - "exclude": [ - "test/**", - "dist/**" - ] - }, - "license": "(Apache-2.0 AND MIT)" -} diff --git a/packages/validator/test/fixtures.js b/packages/validator/test/fixtures.js deleted file mode 100644 index 678e9516..00000000 --- a/packages/validator/test/fixtures.js +++ /dev/null @@ -1,18 +0,0 @@ -import * as ed25519 from '@ucanto/principal/ed25519' - -/** did:key:z6Mkqa4oY9Z5Pf5tUcjLHLUsDjKwMC95HGXdE1j22jkbhz6r */ -export const alice = ed25519.parse( - 'MgCZT5vOnYZoVAeyjnzuJIVY9J4LNtJ+f8Js0cTPuKUpFne0BVEDJjEu6quFIU8yp91/TY/+MYK8GvlKoTDnqOCovCVM=' -) -/** did:key:z6MkffDZCkCTWreg8868fG1FGFogcJj5X6PY93pPcWDn9bob */ -export const bob = ed25519.parse( - 'MgCYbj5AJfVvdrjkjNCxB3iAUwx7RQHVQ7H1sKyHy46Iose0BEevXgL1V73PD9snOCIoONgb+yQ9sycYchQC8kygR4qY=' -) -/** did:key:z6MktafZTREjJkvV5mfJxcLpNBoVPwDLhTuMg9ng7dY4zMAL */ -export const mallory = ed25519.parse( - 'MgCYtH0AvYxiQwBG6+ZXcwlXywq9tI50G2mCAUJbwrrahkO0B0elFYkl3Ulf3Q3A/EvcVY0utb4etiSE8e6pi4H0FEmU=' -) - -export const service = ed25519.parse( - 'MgCYKXoHVy7Vk4/QjcEGi+MCqjntUiasxXJ8uJKY0qh11e+0Bs8WsdqGK7xothgrDzzWD0ME7ynPjz2okXDh8537lId8=' -) diff --git a/packages/validator/test/test.js b/packages/validator/test/test.js deleted file mode 100644 index dbe6d8ec..00000000 --- a/packages/validator/test/test.js +++ /dev/null @@ -1,6 +0,0 @@ -import { assert, use } from 'chai' -import subset from 'chai-subset' -use(subset) - -export const test = it -export { assert } diff --git a/packages/validator/tsconfig.json b/packages/validator/tsconfig.json deleted file mode 100644 index 46d91b63..00000000 --- a/packages/validator/tsconfig.json +++ /dev/null @@ -1,108 +0,0 @@ -{ - "compilerOptions": { - /* Visit https://aka.ms/tsconfig.json to read more about this file */ - - /* Projects */ - "incremental": true /* Enable incremental compilation */, - "composite": true /* Enable constraints that allow a TypeScript project to be used with project references. */, - // "tsBuildInfoFile": "./dist", /* Specify the folder for .tsbuildinfo incremental compilation files. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "ES2020" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */, - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */ - // "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - - /* Modules */ - "module": "ES2020" /* Specify what module code is generated. */, - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */, - "baseUrl": "./" /* Specify the base directory to resolve non-relative module names. */, - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "resolveJsonModule": true, /* Enable importing .json files */ - // "noResolve": true, /* Disallow `import`s, `require`s or ``s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - "allowJs": true /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */, - "checkJs": true /* Enable error reporting in type-checked JavaScript files. */, - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */ - - /* Emit */ - // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - "declarationMap": true /* Create sourcemaps for d.ts files. */, - "emitDeclarationOnly": true /* Only output d.ts files and not JavaScript files. */, - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */ - "outDir": "./dist/" /* Specify an output folder for all emitted files. */, - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */, - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */, - - /* Type Checking */ - "strict": true /* Enable all strict type-checking options. */, - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */ - // "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */ - // "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, - "include": ["src", "test"], - "references": [ - { "path": "../interface" }, - { "path": "../client" }, - { "path": "../principal" }, - { "path": "../core" } - ] -} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5dd8679e..def013ed 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -53,11 +53,13 @@ importers: '@ipld/dag-cbor': ^9.0.0 '@ipld/dag-ucan': ^3.2.0 '@types/chai': ^4.3.3 + '@types/chai-subset': ^1.3.3 '@types/mocha': ^9.1.0 '@ucanto/interface': ^4.1.0 '@ucanto/principal': ^4.1.0 c8: ^7.11.0 chai: ^4.3.6 + chai-subset: ^1.6.0 mocha: ^10.1.0 multiformats: ^11.0.0 nyc: ^15.1.0 @@ -71,10 +73,12 @@ importers: multiformats: 11.0.1 devDependencies: '@types/chai': 4.3.4 + '@types/chai-subset': 1.3.3 '@types/mocha': 9.1.1 '@ucanto/principal': link:../principal c8: 7.12.0 chai: 4.3.7 + chai-subset: 1.6.0 mocha: 10.2.0 nyc: 15.1.0 playwright-test: 8.1.2 @@ -132,7 +136,6 @@ importers: '@ucanto/interface': ^4.1.0 '@ucanto/principal': ^4.1.0 '@ucanto/transport': ^4.1.0 - '@ucanto/validator': ^4.1.0 '@web-std/fetch': ^4.1.0 '@web-std/file': ^3.0.2 c8: ^7.11.0 @@ -146,7 +149,6 @@ importers: dependencies: '@ucanto/core': link:../core '@ucanto/interface': link:../interface - '@ucanto/validator': link:../validator devDependencies: '@types/chai': 4.3.4 '@types/chai-subset': 1.3.3 @@ -200,45 +202,6 @@ importers: playwright-test: 8.1.2 typescript: 4.9.4 - packages/validator: - specifiers: - '@ipld/car': ^5.0.3 - '@ipld/dag-cbor': ^8.0.0 - '@types/chai': ^4.3.3 - '@types/chai-subset': ^1.3.3 - '@types/mocha': ^9.1.0 - '@ucanto/client': ^4.1.0 - '@ucanto/core': ^4.1.0 - '@ucanto/interface': ^4.1.0 - '@ucanto/principal': ^4.1.0 - c8: ^7.11.0 - chai: ^4.3.6 - chai-subset: ^1.6.0 - mocha: ^10.1.0 - multiformats: ^11.0.0 - nyc: ^15.1.0 - playwright-test: ^8.1.1 - typescript: ^4.9.4 - dependencies: - '@ipld/car': 5.0.3 - '@ipld/dag-cbor': 8.0.1 - '@ucanto/core': link:../core - '@ucanto/interface': link:../interface - multiformats: 11.0.1 - devDependencies: - '@types/chai': 4.3.4 - '@types/chai-subset': 1.3.3 - '@types/mocha': 9.1.1 - '@ucanto/client': link:../client - '@ucanto/principal': link:../principal - c8: 7.12.0 - chai: 4.3.7 - chai-subset: 1.6.0 - mocha: 10.2.0 - nyc: 15.1.0 - playwright-test: 8.1.2 - typescript: 4.9.4 - packages: /@ampproject/remapping/2.2.0: @@ -462,14 +425,6 @@ packages: varint: 6.0.0 dev: false - /@ipld/dag-cbor/8.0.1: - resolution: {integrity: sha512-mHRuzgGXNk0Y5W7nNQdN37qJiig1Kdgf92icBVFRUNtBc9Ezl5DIdWfiGWBucHBrhqPBncxoH3As9cHPIRozxA==} - engines: {node: '>=16.0.0', npm: '>=7.0.0'} - dependencies: - cborg: 1.10.0 - multiformats: 11.0.1 - dev: false - /@ipld/dag-cbor/9.0.0: resolution: {integrity: sha512-zdsiSiYDEOIDW7mmWOYWC9gukjXO+F8wqxz/LfN7iSwTfIyipC8+UQrCbPupFMRb/33XQTZk8yl3My8vUQBRoA==} engines: {node: '>=16.0.0', npm: '>=7.0.0'}