import type { Services } from '../../../services/mod.js' import type { EnsureDevicePlatformError, EnsureDeviceClientError, DeviceExpiredError, DeviceDeregisteredError, } from '../../../services/platform/licensing/ensure-device/errors.js' import type { DecodedDeviceRegistrationManifest, DecodeDeviceRegistrationManifestError, DeviceRegistration, DeviceRegistrationManifest, EncodeDeviceRegistrationManifestError, } from '../../../domain/device-registration-manifest.js' import { DeviceRegistrationError } from '../../../services/platform/licensing/ensure-device/errors.js' import { decodeDeviceRegistrationManifest, encodeDeviceRegistrationManifest, } from '../../../domain/device-registration-manifest.js' import { isError, makeError, unwrapResult, } from '../../../framework/types/result.js' import type { GatherDeviceInformationError } from '../../../services/device/gather.js' import { decodeJson } from '../../../framework/json/mod.js' interface Options { deps: { services: Services } } export interface EnsureDeviceDto { manifest: DeviceRegistrationManifest } export function buildEnsure(options: Options) { return async function ensure(dto: EnsureDeviceDto) { const { deps: { services }, } = options const decodeDeviceRegistrationManifestResult = decodeDeviceRegistrationManifest(dto.manifest) if (isError(decodeDeviceRegistrationManifestResult)) { return makeError( new DeviceRegistrationError( 'Unable to ensure the device integrity, because the given registration manifest is malformed', ), ) } const manifest = unwrapResult(decodeDeviceRegistrationManifestResult) const gatherResult = await services.device.gather() if (isError(gatherResult)) { return gatherResult } const device = unwrapResult(gatherResult) const resultOfDecryptingDeviceRegistration = await services.crypto.decrypt({ privateJwk: manifest.encryption.keypair.privateKey, encryptedContents: manifest.registration, }) if (isError(resultOfDecryptingDeviceRegistration)) { return makeError( new DeviceRegistrationError( 'Unable to ensure the device integrity, because the given registration manifest is malformed', ), ) } const jsonEncodedDeviceRegistration = unwrapResult( resultOfDecryptingDeviceRegistration, ) const resultOfDecodingDeviceRegistration = decodeJson( jsonEncodedDeviceRegistration, ) if (isError(resultOfDecodingDeviceRegistration)) { return makeError( new DeviceRegistrationError( 'Unable to ensure the device integrity, because the given registration manifest is malformed', ), ) } const deviceRegistration = unwrapResult(resultOfDecodingDeviceRegistration) const ensureResult = await services.platform.licensing.ensureDevice({ device: { id: deviceRegistration.device.id, fingerprint: device.fingerprint, }, license: { jwt: deviceRegistration.license.jwt, }, }) if (isError(ensureResult)) { return ensureResult } const registration = unwrapResult(ensureResult) const ensuredManifest: DecodedDeviceRegistrationManifest = { _tag: 'DeviceRegistrationManifest', encryption: { keypair: manifest.encryption.keypair, }, signing: { keypair: manifest.signing.keypair, }, registration, } return encodeDeviceRegistrationManifest(ensuredManifest) } } export type EnsureDeviceError = | EnsureDevicePlatformError | EnsureDeviceClientError | DeviceExpiredError | DeviceDeregisteredError | DeviceRegistrationError | GatherDeviceInformationError | DecodeDeviceRegistrationManifestError | EncodeDeviceRegistrationManifestError