Skip to content

Commit

Permalink
feat!: bump to 0.9 (#116)
Browse files Browse the repository at this point in the history
- bump major for 0.9 and change urls
- build service async in the agent
  • Loading branch information
hugomrdias authored Oct 18, 2022
1 parent 561c68b commit 29cf63c
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 66 deletions.
2 changes: 1 addition & 1 deletion packages/access-api/src/service/voucher-redeem.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export function voucherRedeemProvider(ctx) {
})

ctx.config.METRICS.writeDataPoint({
blobs: [ctx.config.ENV, 'new_account'],
blobs: [ctx.config.ENV, 'new_account_v1'],
doubles: [1],
})

Expand Down
15 changes: 7 additions & 8 deletions packages/access-api/test/helpers/context.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Signer } from '@ucanto/principal/ed25519'
import { buildConnection } from '@web3-storage/access'
import { connection } from '@web3-storage/access'
import anyTest from 'ava'
import dotenv from 'dotenv'
import { Miniflare } from 'miniflare'
Expand Down Expand Up @@ -38,15 +38,14 @@ export async function context() {
modules: true,
bindings,
})
const { connection } = await buildConnection(
principal,
// @ts-ignore
mf.dispatchFetch.bind(mf),
new URL('http://localhost:8787')
)
return {
mf,
conn: connection,
conn: await connection(
principal,
// @ts-ignore
mf.dispatchFetch.bind(mf),
new URL('http://localhost:8787')
),
service: Signer.parse(bindings.PRIVATE_KEY),
issuer: principal,
}
Expand Down
4 changes: 2 additions & 2 deletions packages/access-api/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ unsafe = { bindings = [
# Staging
[env.staging]
name = "w3access-staging"
routes = [{ pattern = "access-api-staging.web3.storage", custom_domain = true }]
workers_dev = true
vars = { ENV = "staging", DEBUG = "false" }
build = { command = "scripts/cli.js build --env staging", watch_dir = "src" }
kv_namespaces = [
Expand All @@ -76,7 +76,7 @@ unsafe = { bindings = [
# Production
[env.production]
name = "w3access"
routes = [{ pattern = "access-api.web3.storage", custom_domain = true }]
routes = [{ pattern = "access.web3.storage", custom_domain = true }]
vars = { ENV = "production", DEBUG = "false" }
build = { command = "scripts/cli.js build --env production", watch_dir = "src" }
kv_namespaces = [
Expand Down
87 changes: 42 additions & 45 deletions packages/access/src/agent.js
Original file line number Diff line number Diff line change
@@ -1,27 +1,26 @@
import * as DID from '@ipld/dag-ucan/did'
import * as Client from '@ucanto/client'
import { delegate } from '@ucanto/core'
// @ts-ignore
// eslint-disable-next-line no-unused-vars
import * as Ucanto from '@ucanto/interface'
import * as DID from '@ipld/dag-ucan/did'
import { Peer } from './awake/peer.js'
import * as Client from '@ucanto/client'
import * as CAR from '@ucanto/transport/car'
import * as CBOR from '@ucanto/transport/cbor'
import * as HTTP from '@ucanto/transport/http'
import { delegate } from '@ucanto/core'
import * as Voucher from './capabilities/voucher.js'
import { URI } from '@ucanto/validator'
import { Peer } from './awake/peer.js'
import * as Account from './capabilities/account.js'
import { Websocket } from './utils/ws.js'
import * as Voucher from './capabilities/voucher.js'
import { stringToDelegation } from './encoding.js'
import { URI } from '@ucanto/validator'
import { Websocket } from './utils/ws.js'

/**
* @template T
* @typedef {{
* store: import('./stores/types').Store<T>
* connection: Ucanto.ConnectionView<import('./types').Service>,
* url?: URL,
* fetch?: typeof fetch
* service: Ucanto.Principal
* fetch: typeof fetch
* data: import('./stores/types').StoreData<T>
* }} AgentOptions
*/
Expand All @@ -35,20 +34,16 @@ import { URI } from '@ucanto/validator'
* }} AgentCreateOptions
*/

const HOST = 'https://access-api.web3.storage'
const HOST = 'https://access.web3.storage'

/**
* @template {string} T
* @param {Ucanto.Principal<T>} principal
* @param {typeof fetch} _fetch
* @param {URL} url
* @returns { Promise<{service: Ucanto.UCAN.PrincipalView, connection: import('@ucanto/interface').ConnectionView<import('./types').Service>}>}
* @returns { Promise<import('@ucanto/interface').ConnectionView<import('./types').Service>>}
*/
export async function buildConnection(principal, _fetch, url) {
const rsp = await _fetch(url + 'version')
const { did } = await rsp.json()
const service = DID.parse(did)

export async function connection(principal, _fetch, url) {
const connection = Client.connect({
id: principal,
encoder: CAR,
Expand All @@ -60,36 +55,33 @@ export async function buildConnection(principal, _fetch, url) {
}),
})

return { service, connection }
return connection
}

/**
* @template {Ucanto.Signer} T
* Agent
*/
export class Agent {
/** @type {Ucanto.Principal|undefined} */
#service

/** @type {typeof fetch} */
#fetch

/**
* @param {AgentOptions<T>} opts
*/
constructor(opts) {
this.store = opts.store
this.service = opts.service
this.url = opts.url || new URL(HOST)
this.fetch = opts.fetch
this.connection = opts.connection
this.data = opts.data
this.issuer = opts.data.principal
this.store = opts.store
this.data = opts.data

// validate fetch implementation
if (!this.fetch) {
if (typeof globalThis.fetch !== 'undefined') {
this.fetch = globalThis.fetch.bind(globalThis)
} else {
throw new TypeError(
`Agent got undefined \`fetch\`. Try passing in a \`fetch\` implementation explicitly.`
)
}
}
// private
this.#fetch = opts.fetch
this.#service = undefined
}

/**
Expand All @@ -112,21 +104,25 @@ export class Agent {
}

const data = await opts.store.load()
const { connection, service } = await buildConnection(
data.principal,
_fetch,
url
)
return new Agent({
connection,
service,
connection: await connection(data.principal, _fetch, url),
fetch: _fetch,
url,
store: opts.store,
data,
})
}

async service() {
if (this.#service) {
return this.#service
}
const rsp = await this.#fetch(this.url + 'version')
const { did } = await rsp.json()
this.#service = DID.parse(did)
return this.#service
}

did() {
return this.data.principal.did()
}
Expand All @@ -136,6 +132,7 @@ export class Agent {
*/
async createAccount(email) {
const account = await this.store.createAccount()
const service = await this.service()
const accDelegation = await delegate({
// @ts-ignore
issuer: account,
Expand All @@ -156,12 +153,12 @@ export class Agent {
const inv = await Voucher.claim
.invoke({
issuer: this.data.principal,
audience: this.service,
audience: service,
with: account.did(),
nb: {
identity: URI.from(`mailto:${email}`),
product: 'product:free',
service: this.service.did(),
service: service.did(),
},
proofs: [accDelegation],
})
Expand All @@ -171,13 +168,13 @@ export class Agent {
throw new Error('Account creation failed', { cause: inv.error })
}

const voucherRedeem = await this._waitForVoucherRedeem()
const voucherRedeem = await this.#waitForVoucherRedeem()

const accInv = await Voucher.redeem
.invoke({
issuer: this.data.principal,
audience: this.service,
with: this.service.did(),
audience: service,
with: service.did(),
nb: {
account: account.did(),
identity: voucherRedeem.capabilities[0].nb.identity,
Expand All @@ -196,7 +193,7 @@ export class Agent {
this.store.save(this.data)
}

async _waitForVoucherRedeem() {
async #waitForVoucherRedeem() {
const ws = new Websocket(this.url, 'validate-ws')
await ws.open()
ws.send({
Expand Down Expand Up @@ -267,7 +264,7 @@ export class Agent {
const inv = await Account.info
.invoke({
issuer: this.issuer,
audience: this.service,
audience: await this.service(),
with: account,
proofs,
})
Expand Down
6 changes: 2 additions & 4 deletions packages/access/src/awake/peer.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ export class Peer {

// step3 - awake/res send
const ucan = await UCAN.issue({
issuer: this.agent.data.principal,
issuer: this.agent.issuer,
audience: this.nextdid,
capabilities: [{ with: 'awake:', can: '*' }],
facts: [
Expand Down Expand Up @@ -188,9 +188,7 @@ export class Peer {

// Pin signature
const bytes = u8.fromString(this.nextdid.did() + this.pin.toString())
const signed = await this.agent.data.principal.sign(
await sha256.encode(bytes)
)
const signed = await this.agent.issuer.sign(await sha256.encode(bytes))
this.channel.sendMsg(this.nextdid, {
did: this.did,
sig: u8.toString(signed, 'base64'),
Expand Down
4 changes: 2 additions & 2 deletions packages/access/src/cli/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Verifier } from '@ucanto/principal/ed25519'

/** @type {Record<string,string>} */
const envs = {
production: 'https://access-api-staging.web3.storage',
staging: 'https://access-api.web3.storage',
production: 'https://access.web3.storage',
staging: 'https://w3access-staging.protocol-labs.workers.dev',
dev: 'https://w3access-dev.protocol-labs.workers.dev',
local: 'http://127.0.0.1:8787',
}
Expand Down
2 changes: 2 additions & 0 deletions packages/access/test/awake.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,12 @@ describe('awake', function () {
const agent1 = await Agent.create({
store: await StoreMemory.create(),
fetch: globalThis.fetch || fetch,
url: new URL('http://127.0.0.1:8787'),
})
const agent2 = await Agent.create({
store: await StoreMemory.create(),
fetch: globalThis.fetch || fetch,
url: new URL('http://127.0.0.1:8787'),
})
const responder = agent1.peer(ws1)
const requestor = agent2.peer(ws2)
Expand Down
11 changes: 7 additions & 4 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,25 @@ pnpm install
npx simple-git-hooks
```

## Deployments
## Deployments

### Access API

There's 3 environments prodution, staging and dev. The URLs are:
- Prodution: https://access-api.web3.storage
- Staging: https://access-api-staging.web3.storage

- Prodution: https://access.web3.storage
- Staging: https://w3access-staging.protocol-labs.workers.dev
- Dev: https://w3access-dev.protocol-labs.workers.dev

The history and the current deployed commits can be checked at https://github.com/web3-storage/w3-protocol/deployments. The deployed commit hash for each environment can also be checked directly in the API .ie [`https://access-api.web3.storage/version`](https://access-api.web3.storage/version).
The history and the current deployed commits can be checked at https://github.com/web3-storage/w3-protocol/deployments. The deployed commit hash for each environment can also be checked directly in the API .ie [`https://access.web3.storage/version`](https://access.web3.storage/version).

#### Deployment Flow

1. Each PR deploys to `dev`, we should add support for unique deployments and remove `dev` completely.
2. Each Access API **Release** PR deploys to `staging` every time the CI runs for that PR.
- Note: Any change to the folder `packages/access-api` will update the Access API release PR and trigger a new deployment to `staging`.
3. After merging an Access API release PR to `main` CI will deploy to `prodution`.

#### Reverting a bad deployment

When something bad is deployed to any environment it can be reverted by going to the [Manual Deploy Workflow](https://github.com/web3-storage/w3-protocol/actions/workflows/manual.yml) select a branch or tag, the package (in this case `access-api`) and the environment and run the workflow.

0 comments on commit 29cf63c

Please sign in to comment.