import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";

const root = fileURLToPath(new URL("../../../", import.meta.url));
const source = (relative: string) => readFileSync(`${root}/${relative}`, "utf8");

describe("ADR-0009 deployment trust boundary", () => {
  it("keeps PostgreSQL and the privileged control plane behind loopback HTTPS ingress", () => {
    const deploy = source("infra/dogfood/deploy-debian3.sh");
    expect(deploy).toContain("AWP_CONTROL_HOST=127.0.0.1");
    expect(deploy).toContain("AWP_WEB_HOST=127.0.0.1");
    expect(deploy).toContain("AWP_EXECUTION_CALLBACK_BASE_URL=https://$TAILSCALE_DNS_NAME/api");
    expect(deploy).toContain('tailscale serve --bg --yes --https=443 "http://127.0.0.1:$WEB_PORT"');
    expect(deploy).toContain('MISE_BIN="${AWP_MISE_BIN:-/home/user/.local/bin/mise}"');
    expect(deploy).toContain('"$MISE_BIN" x node@24 -- pnpm install --frozen-lockfile');
    expect(deploy).toContain('"$MISE_BIN" x node@24 -- pnpm build');
    expect(deploy).toContain("AWP_OPERATOR_PASSWORD_HASH=$OPERATOR_PASSWORD_HASH");
    expect(deploy).toContain("operator-password-hash");
    expect(deploy).toContain(
      'MODEL_GATEWAY_CLUSTER_IP="$(kubectl -n awp-system get service awp-model-gateway',
    );
    expect(deploy).toContain("AWP_MODEL_GATEWAY_URL=http://$MODEL_GATEWAY_CLUSTER_IP:32180/v1");
    expect(deploy).not.toContain("awp-model-gateway.awp-system.svc.cluster.local");

    const webEnvironment = deploy.match(
      /cat > "\$CONFIG_DIR\/web\.env" <<EOF\n([\s\S]*?)\nEOF/u,
    )?.[1];
    expect(webEnvironment).toBeDefined();
    expect(webEnvironment).not.toMatch(/DATABASE_URL|POSTGRES|OPERATOR_PASSWORD_HASH/u);

    expect(deploy).toContain('PUBLICATION_APP_ID_FILE="$CONFIG_DIR/github-app-id"');
    expect(deploy).toContain(
      'PUBLICATION_INSTALLATION_ID_FILE="$CONFIG_DIR/github-app-installation-id"',
    );
    expect(deploy).toContain(
      'PUBLICATION_APP_PRIVATE_KEY_FILE="$CONFIG_DIR/github-app-private-key"',
    );
    expect(deploy).toContain("configure exactly one GitHub publication authority");
    expect(deploy).toContain("GitHub App publication authority requires github-app-id");
    expect(deploy).toContain("AWP_GITHUB_PUBLICATION_APP_PRIVATE_KEY_FILE=%s\\n");
    expect(deploy).toContain("AWP_GITHUB_PUBLICATION_REPOSITORY=%s\\n");
    expect(deploy).not.toMatch(/AWP_GITHUB_PUBLICATION_APP_PRIVATE_KEY=/u);
    expect(deploy).not.toMatch(/cat .*github-app-private-key.*control-plane\.env/u);
  });

  it("keeps the public web process database-free and never trusts a caller-supplied session header", () => {
    const webPackage = JSON.parse(source("apps/web/package.json")) as {
      dependencies?: Record<string, string>;
    };
    expect(Object.keys(webPackage.dependencies ?? {})).not.toContain("@awp/persistence");
    expect(Object.keys(webPackage.dependencies ?? {})).not.toContain("postgres");

    const webServer = source("apps/web/src/server.ts");
    expect(webServer).not.toMatch(/request\.headers\[["']x-awp-session["']\]/u);
    expect(webServer).toContain("internalSessionHeaders(token");
    expect(webServer).toContain('"/api/internal/execution/complete"');
    expect(webServer).toContain('"/api/internal/execution/fail"');
    expect(webServer).toContain('"/api/internal/execution/review"');
  });

  it("defaults the control-plane HTTP listener to loopback", () => {
    const server = source("apps/control-plane/src/server.ts");
    expect(server).toContain('const host = input.host ?? "127.0.0.1"');
    expect(server).toContain("serve({ fetch: app.fetch, port, hostname: host })");
  });

  it("does not enable the post-commit crash hook in dogfood deployment configuration", () => {
    const deploy = source("infra/dogfood/deploy-debian3.sh");
    expect(deploy).not.toContain("AWP_CRASH_AFTER_STEP_COMMIT");
  });
  it("fails closed when control-plane startup aborts before a listener is healthy", () => {
    const server = source("apps/control-plane/src/server.ts");
    expect(server).toContain("let startupDbosRuntime");
    expect(server).toContain("let startupServer");
    expect(server).toContain("await runtime.close()");
    expect(server).toContain("await startupDbosRuntime.close()");
    expect(server).toContain("startupServer?.close");
    expect(server).toContain("process.exit(1)");
    expect(server).not.toContain("process.exitCode = 1");
  });
  it("serializes the complete dogfood deployment transaction", () => {
    const deploy = source("infra/dogfood/deploy-debian3.sh");
    expect(deploy).toContain('DEPLOY_LOCK="$APP_ROOT/.deploy.lock"');
    expect(deploy).toContain('exec 9>"$DEPLOY_LOCK"');
    expect(deploy).toContain('flock -w "${AWP_DOGFOOD_DEPLOY_LOCK_WAIT_SEC:-900}" 9');
    expect(deploy.indexOf('exec 9>"$DEPLOY_LOCK"')).toBeLessThan(
      deploy.indexOf('git -C "$APP_ROOT/source-seed" fetch'),
    );
    expect(deploy.indexOf('exec 9>"$DEPLOY_LOCK"')).toBeLessThan(
      deploy.indexOf("systemctl --user stop awp-dogfood-web.service"),
    );
  });

  it("deploys only an explicitly requested current main commit and retains source identity proof", () => {
    const deploy = source("infra/dogfood/deploy-debian3.sh");
    expect(deploy).toContain('REQUESTED_SOURCE_SHA="${AWP_DOGFOOD_SOURCE_SHA:-}"');
    expect(deploy).toContain(
      "AWP_DOGFOOD_SOURCE_SHA must name the exact 40-hex canonical main commit",
    );
    expect(deploy).toContain("fetch --prune origin +refs/heads/main:refs/remotes/origin/main");
    expect(deploy).toContain(
      'SOURCE_SHA="$(git -C "$APP_ROOT/source-seed" rev-parse refs/remotes/origin/main)"',
    );
    expect(deploy).toContain(
      'SOURCE_TREE="$(git -C "$APP_ROOT/source-seed" rev-parse "$SOURCE_SHA^{tree}")"',
    );
    expect(deploy).toContain("AWP dogfood source race: requested");
    expect(deploy).toContain('archive --format=tar "$SOURCE_SHA"');
    expect(deploy).not.toContain("rsync -a --delete --exclude='.git' ./");
    expect(deploy).toContain("AWP_DEPLOYED_SOURCE_SHA=$SOURCE_SHA");
    expect(deploy).toContain("AWP_DEPLOYED_SOURCE_TREE=$SOURCE_TREE");
    expect(deploy).toContain(".source.sha == $sha and .source.tree == $tree");
    expect(deploy).toContain("deployment-receipt.json");
    expect(deploy.indexOf("systemctl --user stop awp-dogfood-web.service")).toBeLessThan(
      deploy.indexOf('mv "$APP_ROOT/repo.next" "$APP_ROOT/repo"'),
    );
    expect(deploy.indexOf('mv "$APP_ROOT/repo.next" "$APP_ROOT/repo"')).toBeLessThan(
      deploy.indexOf("systemctl --user restart awp-dogfood-control-plane.service"),
    );

    const server = source("apps/control-plane/src/server.ts");
    expect(server).toContain("process.env.AWP_DEPLOYED_SOURCE_SHA");
    expect(server).toContain("process.env.AWP_DEPLOYED_SOURCE_TREE");
    expect(server).toContain("source: { sha: deployedSourceSha, tree: deployedSourceTree }");
  });
});
