<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

/**
 * Proving that a customer owns the domain they pointed at us.
 *
 * Without this, `custom_domain` was a free-text field: anyone who pointed any
 * hostname at the proxy would be served somebody else's Nextcloud under their
 * own name, and the certificate would be issued for it too. The DNS is the
 * proof — a TXT record only the domain's owner can create.
 *
 * Verification is not a one-off. A token checked once and never again can be
 * removed the minute after, and a domain that later lapses and is registered by
 * somebody else keeps resolving to the same instance. So the record has to stay
 * in place and is re-read nightly; when it goes, the domain stops being served.
 */
return new class extends Migration
{
    public function up(): void
    {
        Schema::table('instances', function (Blueprint $table) {
            // The token the customer publishes. Random per domain, not derived
            // from anything — a token computed from the domain name would be
            // forgeable by anybody who read the algorithm once.
            $table->string('domain_token', 40)->nullable()->after('custom_domain');

            // Null until the record has been seen. This is the flag the proxy,
            // the certificate and Nextcloud's trusted_domains all key off:
            // unverified means the domain does not exist as far as we are
            // concerned, and the proxy answers nothing at all.
            $table->timestamp('domain_verified_at')->nullable()->after('domain_token');

            // The last time the record was actually read, successful or not,
            // and what went wrong. Separate from verified_at so a customer can
            // see "checked ten minutes ago, still missing" rather than silence.
            $table->timestamp('domain_checked_at')->nullable()->after('domain_verified_at');
            $table->string('domain_error', 32)->nullable()->after('domain_checked_at');

            // How long it has been failing. One failed lookup is a nameserver
            // having a bad minute; days of them is a domain that has moved on.
            $table->unsignedSmallInteger('domain_failures')->default(0)->after('domain_error');
        });
    }

    public function down(): void
    {
        Schema::table('instances', function (Blueprint $table) {
            $table->dropColumn([
                'domain_token', 'domain_verified_at', 'domain_checked_at',
                'domain_error', 'domain_failures',
            ]);
        });
    }
};
