feat(chat): share a chat by link — anonymous read-only /shared/<token> page, share/unshare

This commit is contained in:
2026-08-30 01:34:44 -04:00
parent ece93a7c8f
commit 114b115034
28 changed files with 3442 additions and 54 deletions
+66
View File
@@ -17,6 +17,7 @@ import asyncio
import os
import re
import subprocess
import uuid
from collections.abc import AsyncIterator, Iterator
from pathlib import Path
@@ -205,6 +206,7 @@ def test_html_pages_include_history() -> None:
"/tuning.html",
"/git-sources.html",
"/history.html",
"/shared.html", # phase 51: the shared page's static path
):
assert path in caching.HTML_PAGES, f"{path} must be in HTML_PAGES"
@@ -386,3 +388,67 @@ def test_read_body_drains_streaming_response() -> None:
resp = StreamingResponse(content=gen(), media_type="text/html")
assert asyncio.run(caching._read_body(resp)) == b"<a></a>"
# ---------------------------------------------------------------------------
# Phase 51: the dynamic share page — the ``/shared/`` prefix contract
# ---------------------------------------------------------------------------
def _shared_page_app() -> FastAPI:
"""A bare app with the phase-51 route pair + the middleware:
``/shared/<token>`` (``text/html`` — the page the route serves) and
``/api/shared/<token>`` (the JSON read), plus an unknown path."""
app = FastAPI()
@app.get("/shared/{token}", response_class=HTMLResponse)
def shared_page(token: str) -> str:
return (
"<html><head>"
'<link rel="stylesheet" href="/assets/styles.css">'
"</head><body>shared</body></html>"
)
@app.get("/api/shared/{token}")
def shared_api(token: str) -> JSONResponse:
return JSONResponse({"title": "Shared", "messages": []})
@app.get("/some/unknown/path")
def unknown() -> JSONResponse:
return JSONResponse({"ok": True})
caching.configure_caching(app)
return app
def test_middleware_treats_shared_page_path_as_known_html_page() -> None:
"""Phase 51: ``/shared/<uuid>`` joins the HTML_PAGES contract —
``no-cache`` + ``?v=`` asset rewrite on the ``text/html`` body (the
FileResponse body is drained by the existing ``_read_body`` path)."""
client = TestClient(_shared_page_app())
r = client.get(f"/shared/{uuid.uuid4()}")
assert r.status_code == 200
assert r.headers["cache-control"] == "no-cache"
token = caching.asset_version()
assert f'href="/assets/styles.css?v={token}"' in r.text
assert 'href="/assets/styles.css">' not in r.text
def test_middleware_leaves_api_shared_read_untouched() -> None:
"""``/api/shared/<uuid>`` — the JSON read — starts with ``/api/``,
not ``/shared/``: byte-identical pass-through, no injected headers."""
client = TestClient(_shared_page_app())
r = client.get(f"/api/shared/{uuid.uuid4()}")
assert r.status_code == 200
assert "cache-control" not in r.headers
assert r.json() == {"title": "Shared", "messages": []}
def test_middleware_leaves_unknown_paths_untouched() -> None:
"""A path that is neither a known page, ``/shared/*``, nor
``/assets/*`` passes through byte-identical, no headers."""
client = TestClient(_shared_page_app())
r = client.get("/some/unknown/path")
assert r.status_code == 200
assert "cache-control" not in r.headers
assert r.json() == {"ok": True}