import * as Effect from "effect/Effect"; import * as Exit from "effect/Exit"; import type { DomainAPI } from "./domain-api.ts"; import { DomainAccountDenied, DomainAttachmentOutcomeUnknown, DomainReauthorizationRequired, DomainResourceConflict, } from "./domain-errors.ts"; import type { DomainRecord } from "./domain-metadata.ts"; import type { RegistryFailure } from "./installation-errors.ts"; type DomainProvider = Pick; export type SaveDomain = ( domain: DomainRecord, changes: Partial< Pick >, ) => Effect.Effect; export function attachDomain( api: DomainProvider, saved: DomainRecord, save: SaveDomain, ) { return Effect.gen(function* () { let domain = saved; if (!domain.writeIntent) { yield* api.preflight(domain); domain = yield* save(domain, { writeIntent: true }); // Only a definitive rejection reopens permission to PUT. An interrupted, // timed-out or lost reply leaves the durable intent intact for observation. const rejected = ( error: | DomainResourceConflict | DomainAccountDenied | DomainReauthorizationRequired, ) => save(domain, { writeIntent: false, status: "failed", errorCode: error.code, }).pipe(Effect.andThen(Effect.fail(error))); yield* api.attach(domain).pipe( Effect.catchTags({ DomainResourceConflict: rejected, DomainAccountDenied: rejected, DomainReauthorizationRequired: rejected, }), ); } const domainId = yield* api.find(domain); if (!domainId) return yield* new DomainAttachmentOutcomeUnknown(); if (domain.domainId && domain.domainId !== domainId) return yield* new DomainResourceConflict(); if (domain.domainId !== domainId) yield* save(domain, { domainId }); }); } export function verifyDomainMapping( api: Pick, domain: DomainRecord, ) { return Effect.gen(function* () { if ((yield* api.find(domain)) !== domain.domainId) return yield* new DomainResourceConflict(); }); } export function checkDomainHttps( api: Pick, domain: DomainRecord, health: Effect.Effect, ) { return Effect.gen(function* () { yield* verifyDomainMapping(api, domain); // A failed health probe means TLS/runtime readiness is still pending. // Mapping and authorization errors above must remain terminal observations. return Exit.isSuccess(yield* Effect.exit(health)); }); }