|
1 | 1 | import * as Server from '@ucanto/server' |
2 | 2 | import * as CAR from '@ucanto/transport/car' |
| 3 | +import { DIDResolutionError } from '@ucanto/validator' |
| 4 | +import * as Proof from '@storacha/client/proof' |
| 5 | + |
| 6 | +/** |
| 7 | + * Known did:web to did:key mappings for signature verification |
| 8 | + * @type {Record<`did:${string}:${string}`, `did:key:${string}`>} |
| 9 | + */ |
| 10 | +const knownWebDIDs = { |
| 11 | + // Production |
| 12 | + 'did:web:up.storacha.network': 'did:key:z6MkqdncRZ1wj8zxCTDUQ8CRT8NQWd63T7mZRvZUX8B7XDFi', |
| 13 | + 'did:web:web3.storage': 'did:key:z6MkqdncRZ1wj8zxCTDUQ8CRT8NQWd63T7mZRvZUX8B7XDFi', |
| 14 | + 'did:web:w3s.link': 'did:key:z6Mkha3NLZ38QiZXsUHKRHecoumtha3LnbYEL21kXYBFXvo5', |
| 15 | + |
| 16 | + // Staging |
| 17 | + 'did:web:staging.up.storacha.network': 'did:key:z6MkhcbEpJpEvNVDd3n5RurquVdqs5dPU16JDU5VZTDtFgnn', |
| 18 | + 'did:web:staging.web3.storage': 'did:key:z6MkhcbEpJpEvNVDd3n5RurquVdqs5dPU16JDU5VZTDtFgnn', |
| 19 | + 'did:web:staging.w3s.link': 'did:key:z6MkqK1d4thaCEXSGZ6EchJw3tDPhQriwynWDuR55ayATMNf', |
| 20 | +} |
| 21 | + |
| 22 | +/** |
| 23 | + * Resolves did:web DIDs to their corresponding did:key DIDs |
| 24 | + * @param {import('@ucanto/interface').DID} did |
| 25 | + */ |
| 26 | +export const resolveDIDKey = async (did) => { |
| 27 | + if (knownWebDIDs[did]) { |
| 28 | + const didKey = /** @type {`did:key:${string}`} */ (knownWebDIDs[did]) |
| 29 | + return Server.ok([didKey]) // Return array of did:keys |
| 30 | + } |
| 31 | + return Server.error(new DIDResolutionError(did)) |
| 32 | +} |
| 33 | + |
| 34 | +/** |
| 35 | + * @type {import('@ucanto/interface').Delegation[]} |
| 36 | + */ |
| 37 | +let cachedValidatorProofs |
| 38 | + |
| 39 | +/** |
| 40 | + * Loads validator proofs from environment variable. |
| 41 | + * These proofs allow the gateway to validate ucan/attest delegations. |
| 42 | + * |
| 43 | + * @param {{ GATEWAY_VALIDATOR_PROOF?: string }} env |
| 44 | + * @returns {Promise<import('@ucanto/interface').Delegation[]>} |
| 45 | + */ |
| 46 | +export const getValidatorProofs = async (env) => { |
| 47 | + if (cachedValidatorProofs) { |
| 48 | + return cachedValidatorProofs |
| 49 | + } |
| 50 | + cachedValidatorProofs = [] |
| 51 | + if (env.GATEWAY_VALIDATOR_PROOF) { |
| 52 | + try { |
| 53 | + const proof = await Proof.parse(env.GATEWAY_VALIDATOR_PROOF) |
| 54 | + const delegation = /** @type {import('@ucanto/interface').Delegation} */ (proof) |
| 55 | + console.log(`Gateway validator proof loaded: [issuer: ${delegation.issuer.did()}, audience: ${delegation.audience.did()}]`) |
| 56 | + cachedValidatorProofs = [delegation] |
| 57 | + } catch (error) { |
| 58 | + console.error('Failed to parse GATEWAY_VALIDATOR_PROOF:', error) |
| 59 | + } |
| 60 | + } |
| 61 | + return cachedValidatorProofs |
| 62 | +} |
3 | 63 |
|
4 | 64 | /** |
5 | 65 | * Creates a UCAN server. |
6 | 66 | * |
7 | 67 | * @template T |
8 | 68 | * @param {import('../middleware/withUcanInvocationHandler.types.js').Context} ctx |
9 | 69 | * @param {import('./api.types.js').Service<T>} service |
| 70 | + * @param {{ GATEWAY_VALIDATOR_PROOF?: string }} env |
10 | 71 | */ |
11 | | -export function createServer (ctx, service) { |
| 72 | +export async function createServer (ctx, service, env) { |
| 73 | + const proofs = await getValidatorProofs(env) |
| 74 | + console.log('Server validator proofs loaded:', proofs.length) |
| 75 | + if (proofs.length > 0) { |
| 76 | + console.log('First proof details:', { |
| 77 | + issuer: proofs[0].issuer.did(), |
| 78 | + audience: proofs[0].audience.did(), |
| 79 | + capabilities: proofs[0].capabilities.map(c => ({ can: c.can, with: c.with })), |
| 80 | + cid: proofs[0].cid.toString() |
| 81 | + }) |
| 82 | + } |
12 | 83 | return Server.create({ |
13 | 84 | id: ctx.gatewaySigner, |
14 | 85 | codec: CAR.inbound, |
15 | 86 | service, |
16 | 87 | catch: err => console.error(err), |
17 | 88 | // TODO: wire into revocations |
18 | | - validateAuthorization: () => ({ ok: {} }) |
| 89 | + validateAuthorization: () => ({ ok: {} }), |
| 90 | + resolveDIDKey, |
| 91 | + proofs, |
19 | 92 | }) |
20 | 93 | } |
0 commit comments