diff --git a/assets/style.css b/assets/style.css
index 5830091e4871b172f5a81733e334bee986e43711..95b436f4dc02d815bb8adfe6637e9e97ace954ac 100644
--- a/assets/style.css
+++ b/assets/style.css
@@ -179,6 +179,22 @@
   border-bottom: 1px solid GrayText;
 }
 
+.key-list {
+  padding: 0;
+  list-style: none;
+}
+
+.key-card {
+  margin-block: 1rem;
+  padding: 1rem;
+  border: 1px solid GrayText;
+  border-radius: 0.25rem;
+}
+
+.key-card > h3 {
+  margin-top: 0;
+}
+
 .two-column {
   display: grid;
   grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr);
diff --git a/src/http/mod.rs b/src/http/mod.rs
index 6e67ff28a89e308d2ecdd36db7861fb570980963..4ebbd91076362e55b80d0ddd66fe4b0773073a4d 100644
--- a/src/http/mod.rs
+++ b/src/http/mod.rs
@@ -16,7 +16,7 @@
 use axum::Router;
 use axum::body::{Body, Bytes, HttpBody};
 use axum::extract::{
-    ConnectInfo, DefaultBodyLimit, Extension, OriginalUri, Path, Query, RawQuery, Request, State,
+    ConnectInfo, DefaultBodyLimit, Extension, OriginalUri, Path, Query, Request, State,
 };
 use axum::http::{HeaderMap, HeaderName, HeaderValue, Method, StatusCode, header};
 use axum::middleware::{self, Next};
@@ -30,7 +30,6 @@
 
 use crate::account::{AccountError, AccountKeyRequest, AccountService};
 use crate::auth::validate_username;
-use crate::domain::repository::validate_slug;
 use crate::feed_token::FeedTokenService;
 use crate::issue::IssueService;
 use crate::maintenance::MaintenanceGate;
@@ -46,7 +45,6 @@
 use self::public::PublicWeb;
 
 const STYLE: &str = include_str!("../../assets/style.css");
-const MAX_LOCATION_QUERY_BYTES: usize = 512;
 const CONTENT_SECURITY_POLICY: &str = "default-src 'none'; style-src 'self'; form-action 'self'; base-uri 'none'; frame-ancestors 'none'";
 const MAX_BLOCKING_WEB_JOBS: usize = 8;
 const REQUEST_TIMEOUT: Duration = Duration::from_secs(30);
@@ -390,7 +388,6 @@
         .route("/", get(home))
         .route("/healthz", get(health))
         .route("/metrics", get(metrics))
-        .route("/go", get(go_to_repository))
         .route(
             "/signup",
             get(signup_form)
@@ -596,9 +593,6 @@
             StatusCode::OK,
             &request_id.0,
             HomePage {
-                owner: "",
-                repository: "",
-                error: "",
                 signed_in,
                 username: &username,
                 csrf: &csrf,
@@ -621,9 +615,6 @@
             StatusCode::OK,
             &request_id.0,
             HomePage {
-                owner: "",
-                repository: "",
-                error: "",
                 signed_in,
                 username: &username,
                 csrf: &csrf,
@@ -656,38 +647,6 @@
         .header(header::CONTENT_TYPE, "text/plain; charset=utf-8")
         .body(Body::from(body))
         .expect("the readiness response is valid")
-}
-
-async fn go_to_repository(
-    Extension(request_id): Extension<RequestId>,
-    Extension(actor): Extension<RequestActor>,
-    RawQuery(query): RawQuery,
-) -> Response {
-    match parse_location_query(query.as_deref()) {
-        Ok((owner, repository)) => {
-            let location = format!("/{owner}/{repository}");
-            Response::builder()
-                .status(StatusCode::FOUND)
-                .header(header::LOCATION, location)
-                .header(header::CACHE_CONTROL, "no-store")
-                .body(Body::empty())
-                .expect("the repository redirect is valid")
-        }
-        Err(LocationQueryError { owner, repository }) => render_home(
-            StatusCode::BAD_REQUEST,
-            &request_id.0,
-            HomePage {
-                owner: &owner,
-                repository: &repository,
-                error: "Enter a valid lowercase owner and repository.",
-                signed_in: actor.0.is_some(),
-                username: actor.0.as_deref().unwrap_or_default(),
-                csrf: "",
-                repositories: &[],
-                recent_repositories: &[],
-            },
-        ),
-    }
 }
 
 async fn signup_form(
@@ -2271,10 +2230,6 @@
         status,
         &HomeTemplate {
             request_id,
-            owner: page.owner,
-            repository: page.repository,
-            error: page.error,
-            has_error: !page.error.is_empty(),
             signed_in: page.signed_in,
             username: page.username,
             csrf: page.csrf,
@@ -2307,9 +2262,6 @@
 }
 
 struct HomePage<'a> {
-    owner: &'a str,
-    repository: &'a str,
-    error: &'a str,
     signed_in: bool,
     username: &'a str,
     csrf: &'a str,
@@ -2356,28 +2308,6 @@
     }
 }
 
-fn parse_location_query(query: Option<&str>) -> Result<(String, String), LocationQueryError> {
-    let query = query.ok_or_else(LocationQueryError::default)?;
-    if query.len() > MAX_LOCATION_QUERY_BYTES || !valid_percent_encoding(query.as_bytes()) {
-        return Err(LocationQueryError::default());
-    }
-    let mut owner = None;
-    let mut repository = None;
-    for (name, value) in url::form_urlencoded::parse(query.as_bytes()) {
-        match name.as_ref() {
-            "owner" if owner.is_none() => owner = Some(value.into_owned()),
-            "repository" if repository.is_none() => repository = Some(value.into_owned()),
-            _ => return Err(LocationQueryError::default()),
-        }
-    }
-    let owner = owner.unwrap_or_default();
-    let repository = repository.unwrap_or_default();
-    if validate_username(&owner).is_err() || validate_slug(&repository).is_err() {
-        return Err(LocationQueryError { owner, repository });
-    }
-    Ok((owner, repository))
-}
-
 fn valid_percent_encoding(input: &[u8]) -> bool {
     let mut index = 0;
     while index < input.len() {
@@ -2399,12 +2329,6 @@
 #[derive(Clone)]
 struct RequestId(String);
 
-#[derive(Default)]
-struct LocationQueryError {
-    owner: String,
-    repository: String,
-}
-
 #[derive(Default, serde::Deserialize)]
 struct ProfileQuery {
     page: Option<usize>,
@@ -2414,10 +2338,6 @@
 #[template(path = "home.html")]
 struct HomeTemplate<'a> {
     request_id: &'a str,
-    owner: &'a str,
-    repository: &'a str,
-    error: &'a str,
-    has_error: bool,
     signed_in: bool,
     username: &'a str,
     csrf: &'a str,
diff --git a/src/http/public.rs b/src/http/public.rs
index 235f0a42eeb1f238325c01ff6d0687de579cb590..8b99179356acfa0353813a722cdc845596c30902 100644
--- a/src/http/public.rs
+++ b/src/http/public.rs
@@ -1479,7 +1479,11 @@
             if let Ok(content) = std::str::from_utf8(&data)
                 && !data.contains(&0)
             {
-                page.readme_html = markdown::render(content);
+                let base = format!(
+                    "/{}/{}/blob/{}/",
+                    page.owner, page.repository, page.commit_id
+                );
+                page.readme_html = markdown::render_repository(content, &base);
             } else {
                 page.readme_binary = true;
             }
diff --git a/src/markdown.rs b/src/markdown.rs
index 51625fb7772c0026b96fc87b9b79c376dbd7d029..80b052d6a65779acca1d48093bef5fb42746895c 100644
--- a/src/markdown.rs
+++ b/src/markdown.rs
@@ -19,14 +19,45 @@
 }
 
 pub fn render(source: &str) -> RenderedMarkdown {
+    render_with_base(source, None)
+}
+
+pub fn render_repository(source: &str, base: &str) -> RenderedMarkdown {
+    render_with_base(source, Some(base))
+}
+
+fn render_with_base(source: &str, base: Option<&str>) -> RenderedMarkdown {
     if source.len() > MAX_MARKDOWN_BYTES {
         return RenderedMarkdown(LIMIT_MESSAGE.to_owned());
     }
     let mut skipped_link = false;
     let events = Parser::new(source).filter_map(|event| match event {
-        Event::Start(Tag::Link { ref dest_url, .. }) if !safe_link(dest_url) => {
-            skipped_link = true;
-            None
+        Event::Start(Tag::Link {
+            link_type,
+            dest_url,
+            title,
+            id,
+        }) => {
+            if !safe_link(&dest_url) {
+                skipped_link = true;
+                return None;
+            }
+            let destination = match base {
+                Some(base) => resolve_repository_link(&dest_url, base),
+                None => Some(dest_url.to_string()),
+            };
+            match destination {
+                Some(destination) => Some(Event::Start(Tag::Link {
+                    link_type,
+                    dest_url: destination.into(),
+                    title,
+                    id,
+                })),
+                None => {
+                    skipped_link = true;
+                    None
+                }
+            }
         }
         Event::End(TagEnd::Link) if skipped_link => {
             skipped_link = false;
@@ -98,9 +129,37 @@
     }
 }
 
+fn resolve_repository_link(destination: &str, base: &str) -> Option<String> {
+    if Url::parse(destination).is_ok()
+        || destination.starts_with('/')
+        || destination.starts_with('#')
+        || destination.starts_with('?')
+    {
+        return Some(destination.to_owned());
+    }
+
+    let origin = Url::parse("https://tit.invalid/").expect("the Markdown origin is valid");
+    let base = origin.join(base).ok()?;
+    let resolved = base.join(destination).ok()?;
+    if !resolved.path().starts_with(base.path()) {
+        return None;
+    }
+
+    let mut link = resolved.path().to_owned();
+    if let Some(query) = resolved.query() {
+        link.push('?');
+        link.push_str(query);
+    }
+    if let Some(fragment) = resolved.fragment() {
+        link.push('#');
+        link.push_str(fragment);
+    }
+    Some(link)
+}
+
 #[cfg(test)]
 mod tests {
-    use super::render;
+    use super::{render, render_repository};
 
     #[test]
     fn renders_the_documented_subset() {
@@ -147,6 +206,22 @@
 
         assert!(output.contains("Text &amp; markup."));
         assert!(!output.contains("href="));
+    }
+
+    #[test]
+    fn resolves_repository_links_inside_the_current_revision() {
+        let output = render_repository(
+            "[license](LICENSE) [guide](docs/guide.md#start) [anchor](#usage) \
+             [site](/help) [outside](../secret)",
+            "/alice/example/blob/abc123/",
+        )
+        .to_string();
+
+        assert!(output.contains("href=\"/alice/example/blob/abc123/LICENSE\""));
+        assert!(output.contains("href=\"/alice/example/blob/abc123/docs/guide.md#start\""));
+        assert!(output.contains("href=\"#usage\""));
+        assert!(output.contains("href=\"/help\""));
+        assert!(!output.contains("href=\"../secret\""));
     }
 
     #[test]
diff --git a/templates/account-page.html b/templates/account-page.html
index b911571fa1cfeac17a77deba39308f192935ddb5..52279b8a8c76bc625bc3fbf7575e4d35f112352e 100644
--- a/templates/account-page.html
+++ b/templates/account-page.html
@@ -11,7 +11,6 @@
   <div class="two-column">
   <section>
   <h2>Public profile</h2>
-  <p><a href="/{{ username }}">View your public profile</a></p>
   <form action="/account/profile" method="post">
     <input type="hidden" name="csrf" value="{{ csrf }}">
     <div class="field">
@@ -24,6 +23,7 @@
     </div>
     <button type="submit">Save profile</button>
   </form>
+  <p><a href="/{{ username }}">View your public profile</a></p>
   </section>
   <section>
   <h2>Create repository</h2>
@@ -39,50 +39,35 @@
   <p><a href="/feeds">Manage private feed tokens</a></p>
   <h2>Sessions</h2>
   <p><a href="/logout">Log out all sessions</a></p>
-  </section>
-  </div>
-  <section>
   <h2>SSH keys</h2>
-  <div class="table-scroll">
-  <table>
-    <thead>
-      <tr>
-        <th>Label</th>
-        <th>Fingerprint</th>
-        <th>Created</th>
-        <th>Last used</th>
-        <th>State</th>
-        <th>Action</th>
-      </tr>
-    </thead>
-    <tbody>
+  <ul class="key-list">
     {% for key in keys %}
-      <tr>
-        <td>{{ key.label }}</td>
-        <td><code>{{ key.fingerprint }}</code></td>
-        <td>{{ key.created_at }}</td>
-        <td>{{ key.last_used_at }}</td>
-        <td>{% if key.active %}Active{% else %}Revoked{% endif %}</td>
-        <td>
+    <li class="key-card">
+      <h3>{{ key.label }}</h3>
+      <dl>
+        <dt>Fingerprint</dt>
+        <dd><code>{{ key.fingerprint }}</code></dd>
+        <dt>Created</dt>
+        <dd>{{ key.created_at }}</dd>
+        <dt>Last used</dt>
+        <dd>{{ key.last_used_at }}</dd>
+        <dt>State</dt>
+        <dd>{% if key.active %}Active{% else %}Revoked{% endif %}</dd>
+      </dl>
         {% if key.active %}
           {% if active_key_count > 1 %}
-          <form action="/account/keys/revoke" method="post">
-            <input type="hidden" name="csrf" value="{{ csrf }}">
-            <input type="hidden" name="fingerprint" value="{{ key.fingerprint }}">
-            <button type="submit">Revoke</button>
-          </form>
+      <form action="/account/keys/revoke" method="post">
+        <input type="hidden" name="csrf" value="{{ csrf }}">
+        <input type="hidden" name="fingerprint" value="{{ key.fingerprint }}">
+        <button type="submit">Revoke</button>
+      </form>
           {% else %}
-          Final active key
+      <p>This is your final active key.</p>
           {% endif %}
-        {% else %}
-          —
         {% endif %}
-        </td>
-      </tr>
+    </li>
     {% endfor %}
-    </tbody>
-  </table>
-  </div>
+  </ul>
   <h3>Add SSH key</h3>
   <form action="/account/keys/add" method="post">
     <input type="hidden" name="csrf" value="{{ csrf }}">
@@ -97,4 +82,5 @@
     <button type="submit">Add key</button>
   </form>
   </section>
+  </div>
 {% endblock %}
diff --git a/templates/home.html b/templates/home.html
index 6805c686f9331d2677817a511f84c3200416deae..d01825827a282d21cce396622509e45707af74c4 100644
--- a/templates/home.html
+++ b/templates/home.html
@@ -1,9 +1,9 @@
 {% extends "base.html" %}
 {% block title %}{% if signed_in %}{{ username }}{% else %}Repositories{% endif %} · tit{% endblock %}
 {% block content %}
+{% if signed_in %}
   <div class="two-column">
   <section>
-{% if signed_in %}
   <h1>{{ username }}</h1>
   <p><a href="/account">Open your account profile</a>.</p>
   <h2>Your repositories</h2>
@@ -27,8 +27,11 @@
   {% endfor %}
   </ul>
 {% endif %}
+  </section>
+  <section>
   <h2>Recently updated public repositories</h2>
 {% else %}
+  <section>
   <h1>Recently updated public repositories</h1>
 {% endif %}
 {% if recent_repositories.is_empty() %}
@@ -45,23 +48,7 @@
   </ul>
 {% endif %}
   </section>
-  <section>
-  <h2>Open a repository</h2>
-  <p>Enter an owner and a repository to open its public page.</p>
-{% if has_error %}
-  <p class="error" role="alert">{{ error }}</p>
-{% endif %}
-  <form action="/go" method="get">
-    <div class="field">
-      <label for="owner">Owner</label>
-      <input id="owner" name="owner" value="{{ owner }}" required autocomplete="off" autocapitalize="none" spellcheck="false">
-    </div>
-    <div class="field">
-      <label for="repository">Repository</label>
-      <input id="repository" name="repository" value="{{ repository }}" required autocomplete="off" autocapitalize="none" spellcheck="false">
-    </div>
-    <button type="submit">Open repository</button>
-  </form>
-  </section>
+{% if signed_in %}
   </div>
+{% endif %}
 {% endblock %}
diff --git a/tests/public_routes.rs b/tests/public_routes.rs
index c622c042a185444cf00b8e26abc41328ce6e6fa4..519c6052128aa09524fc6b45326110707346b008 100644
--- a/tests/public_routes.rs
+++ b/tests/public_routes.rs
@@ -119,7 +119,14 @@
         assert!(summary_text.contains("<h1>tit fixture</h1>"));
         assert!(summary_text.contains("<strong>safe</strong>"));
         assert!(summary_text.contains("<code>&lt;safe&gt;</code>"));
-        assert!(summary_text.contains("href=\"docs/guide.md\""));
+        assert!(summary_text.contains(&format!(
+            "href=\"/alice/example/blob/{}/docs/guide.md\"",
+            fixture.head
+        )));
+        assert!(summary_text.contains(&format!(
+            "href=\"/alice/example/blob/{}/LICENSE\"",
+            fixture.head
+        )));
         assert!(!summary_text.contains("<script"));
         assert!(!summary_text.contains("javascript:"));
         assert!(!summary_text.contains("<img"));
@@ -1636,9 +1643,10 @@
         ]));
         fs::write(
             worktree.join("README.md"),
-            b"# tit fixture\n\n**safe** and `<safe>`\n\n[guide](docs/guide.md) [bad](javascript:alert(1))\n\n![tracker](https://tracker.example/pixel)\n\n<script>alert(2)</script>\n",
+            b"# tit fixture\n\n**safe** and `<safe>`\n\n[guide](docs/guide.md) [license](LICENSE) [bad](javascript:alert(1))\n\n![tracker](https://tracker.example/pixel)\n\n<script>alert(2)</script>\n",
         )
         .expect("write the README");
+        fs::write(worktree.join("LICENSE"), b"fixture license\n").expect("write the license");
         fs::create_dir(worktree.join("nested")).expect("create a nested directory");
         fs::write(worktree.join("nested/file.txt"), b"first line\n").expect("write the text file");
         fs::write(worktree.join("binary.dat"), b"binary\0content").expect("write the binary file");
diff --git a/tests/serve.rs b/tests/serve.rs
index 74ed3604d91d0d1da4f54d05ed87faf9190ed058..be7169da10a4dc9bb8cd6f3d6732b128035fb509 100644
--- a/tests/serve.rs
+++ b/tests/serve.rs
@@ -220,6 +220,8 @@
     assert!(!account.contains("<a href=\"/recover\">Recover account</a>"));
     assert!(account.contains("action=\"/account/repositories\""));
     assert!(!account.contains("object-format"));
+    assert!(account.contains("<ul class=\"key-list\">"));
+    assert!(!account.contains("<table>"));
     for path in ["/login", "/signup", "/recover"] {
         let response = http_get_with_headers(http, path, &[("Cookie", &cookies)]);
         assert!(response.starts_with("HTTP/1.1 303"));
@@ -229,6 +231,10 @@
     assert!(signed_in_home.contains("<h1>alice</h1>"));
     assert!(signed_in_home.contains("<h2>Your repositories</h2>"));
     assert!(signed_in_home.contains("<h2>Recently updated public repositories</h2>"));
+    assert!(
+        signed_in_home
+            .contains("</section>\n  <section>\n  <h2>Recently updated public repositories</h2>")
+    );
     assert_eq!(signed_in_home.matches(">alice/example</a>").count(), 2);
     assert!(signed_in_home.contains("<a href=\"/account\">Account</a>"));
     assert!(signed_in_home.contains("<a href=\"/logout\">Log out</a>"));
diff --git a/tests/snapshots/web/bad-request.html b/tests/snapshots/web/bad-request.html
deleted file mode 100644
index 99703e680414b471504394f3a05e1f8e39e91d48..0000000000000000000000000000000000000000
--- a/tests/snapshots/web/bad-request.html
+++ /dev/null
@@ -1,59 +1,0 @@
-<!doctype html>
-<html lang="en">
-<head>
-  <meta charset="utf-8">
-  <meta name="viewport" content="width=device-width, initial-scale=1">
-  <title>Repositories · tit</title>
-  <link rel="stylesheet" href="/assets/style.css?v=2">
-</head>
-<body>
-  <a class="skip-link" href="#main">Skip to content</a>
-  <header class="site-header">
-    <a class="brand" href="/" aria-label="tit home">tit</a>
-    <nav aria-label="Primary">
-      <a href="/">Home</a>
-      <a href="/search">Search</a>
-
-      <a href="/signup">Create account</a>
-      <a href="/recover">Recover account</a>
-      <a href="/login">Log in</a>
-
-    </nav>
-  </header>
-  <main id="main">
-
-  <div class="two-column">
-  <section>
-
-  <h1>Recently updated public repositories</h1>
-
-
-  <p>No repositories are available.</p>
-
-  </section>
-  <section>
-  <h2>Open a repository</h2>
-  <p>Enter an owner and a repository to open its public page.</p>
-
-  <p class="error" role="alert">Enter a valid lowercase owner and repository.</p>
-
-  <form action="/go" method="get">
-    <div class="field">
-      <label for="owner">Owner</label>
-      <input id="owner" name="owner" value="&#60;script&#62;" required autocomplete="off" autocapitalize="none" spellcheck="false">
-    </div>
-    <div class="field">
-      <label for="repository">Repository</label>
-      <input id="repository" name="repository" value="example" required autocomplete="off" autocapitalize="none" spellcheck="false">
-    </div>
-    <button type="submit">Open repository</button>
-  </form>
-  </section>
-  </div>
-
-  </main>
-  <footer>
-    <small>Request <code><request-id></code></small>
-  </footer>
-</body>
-</html>
diff --git a/tests/snapshots/web/home.html b/tests/snapshots/web/home.html
index 856a3d36f18924d98500572cb07e598a59ae1fc8..166bf00087108daa7aa8bd8722e2c8f309e6eb18 100644
--- a/tests/snapshots/web/home.html
+++ b/tests/snapshots/web/home.html
@@ -22,32 +22,17 @@
   </header>
   <main id="main">
 
-  <div class="two-column">
-  <section>
 
+  <section>
   <h1>Recently updated public repositories</h1>
+
 
 
   <p>No repositories are available.</p>
 
-  </section>
-  <section>
-  <h2>Open a repository</h2>
-  <p>Enter an owner and a repository to open its public page.</p>
 
-  <form action="/go" method="get">
-    <div class="field">
-      <label for="owner">Owner</label>
-      <input id="owner" name="owner" value="" required autocomplete="off" autocapitalize="none" spellcheck="false">
-    </div>
-    <div class="field">
-      <label for="repository">Repository</label>
-      <input id="repository" name="repository" value="" required autocomplete="off" autocapitalize="none" spellcheck="false">
-    </div>
-    <button type="submit">Open repository</button>
-  </form>
   </section>
-  </div>
+
 
   </main>
   <footer>
diff --git a/tests/web_shell.rs b/tests/web_shell.rs
index 1f4f6a7836ffad274796496a3d453ec5d3148ca2..47eb9e8154472eb2ea90937ae7c41c914b20d613 100644
--- a/tests/web_shell.rs
+++ b/tests/web_shell.rs
@@ -85,9 +85,8 @@
     assert!(home.body.contains("<nav aria-label=\"Primary\">"));
     assert!(home.body.contains("<main id=\"main\">"));
     assert!(home.body.contains("<footer>"));
-    assert!(home.body.contains("<form action=\"/go\" method=\"get\">"));
-    assert!(home.body.contains("name=\"owner\""));
-    assert!(home.body.contains("name=\"repository\""));
+    assert!(!home.body.contains("Open a repository"));
+    assert!(!home.body.contains("<form action=\"/go\""));
     assert!(!home.body.to_ascii_lowercase().contains("<script"));
     assert_security_policy(&home);
     assert_snapshot(&home, include_str!("snapshots/web/home.html"));
@@ -95,6 +94,15 @@
     let request_id = home.header("x-request-id");
     assert_request_id(request_id);
     assert!(home.body.contains(&format!("<code>{request_id}</code>")));
+
+    let removed_repository_form = request(
+        server.address(),
+        "GET",
+        "/go?owner=alice&repository=example",
+        &[],
+    );
+    assert_eq!(removed_repository_form.status, 404);
+    assert_security_policy(&removed_repository_form);
 
     let head = request(server.address(), "HEAD", "/", &[]);
     assert_eq!(head.status, 200);
@@ -139,62 +147,6 @@
     let wrong_signup_method = request(server.address(), "PUT", "/signup", &[]);
     assert_eq!(wrong_signup_method.status, 405);
     assert_eq!(wrong_signup_method.header("allow"), "GET, HEAD, POST");
-
-    server.shutdown().await.expect("stop the Web server");
-}
-
-#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
-async fn submits_the_repository_form_with_plain_http() {
-    let server = start().await;
-
-    let redirect = request(
-        server.address(),
-        "GET",
-        "/go?owner=alice&repository=example",
-        &[],
-    );
-    assert_eq!(redirect.status, 302);
-    assert_eq!(redirect.header("location"), "/alice/example");
-    assert_eq!(redirect.header("cache-control"), "no-store");
-    assert!(redirect.body.is_empty());
-    assert_security_policy(&redirect);
-
-    for path in [
-        "/go",
-        "/go?owner=Alice&repository=example",
-        "/go?owner=alice&repository=../example",
-        "/go?owner=alice&owner=bob&repository=example",
-        "/go?owner=alice&repository=example&extra=value",
-        "/go?owner=alice&repository=%",
-    ] {
-        let response = request(server.address(), "GET", path, &[]);
-        assert_eq!(response.status, 400, "unexpected status for {path}");
-        assert!(response.body.contains("role=\"alert\""));
-        assert!(
-            response
-                .body
-                .contains("Enter a valid lowercase owner and repository.")
-        );
-        assert_security_policy(&response);
-    }
-
-    let injection = request(
-        server.address(),
-        "GET",
-        "/go?owner=%3Cscript%3E&repository=example",
-        &[],
-    );
-    assert_eq!(injection.status, 400);
-    assert!(injection.body.contains("value=\"&#60;script&#62;\""));
-    assert!(!injection.body.contains("value=\"<script>\""));
-    assert!(!injection.body.to_ascii_lowercase().contains("<script"));
-    assert_snapshot(&injection, include_str!("snapshots/web/bad-request.html"));
-
-    let oversized = format!("/go?owner={}&repository=example", "a".repeat(512));
-    assert_eq!(
-        request(server.address(), "GET", &oversized, &[]).status,
-        400
-    );
 
     server.shutdown().await.expect("stop the Web server");
 }
