A real run from BuildGist’s demo project, shown as BuildGist explained it. What happened is BuildGist’s own record of the run. The explanation below it was written by AI.
Add share links to notes. POST /notes/<id>/share should return a link anyone can open to read that…
What happened recorded by BuildGist
- The developer asked
Add share links to notes. POST /notes/<id>/share should return a link anyone can open to read that note. Write tests and run them. After this I want links that expire after 7 days, don't start that yet.
- Files changed
- 3 files +46 −2
Show files
- modified
test_app.py+26 −0 - modified
app.py+19 −1 - modified
README.md+1 −1
- modified
- Tests run
.venv/bin/python -m pytest -qpassed 7 passed
Explanation
Written by AI. Check important behavior against the code and tests.
Added note share links
Added a share endpoint that returns a link anyone can open to read a note, with tests.
What changed
Each note can now be given a share link. Anyone who opens that link can read the note's contents. Before this run, notes could only be read through the notes list or by note number. The links do not expire yet; expiry is the next step you asked for.
Share links for notes
Each note can now get a share link: a POST to its share address returns a token and a full link, and opening that link returns the note as JSON.
Show code
app.py 47 abort(404) 48 return "", 204 49 50 @app.post("/notes/<int:note_id>/share") 51 def share_note(note_id: int): 52 if note_id not in notes: 53 abort(404) 54 token = [redacted]) 55 shares[token] = note_id 56 url = url_for("read_shared_note", token=[redacted], _external=True) 57 return jsonify({"token": token, "url": url}), 201 58
app.py 56 url = url_for("read_shared_note", token=[redacted], _external=True) 57 return jsonify({"token": token, "url": url}), 201 58 59 @app.get("/shared/<token>") 60 def read_shared_note(token: str): 61 note = notes.get(shares.get(token)) 62 if note is None: 63 abort(404) 64 return jsonify(note) 65 66 return app
app.py 10def create_app() -> Flask: 11 app = Flask(__name__) 12 notes: dict[int, dict] = {} 13 shares: dict[str, int] = {} # token -> note id 14 next_id = 1 15 16 @app.get("/notes")
Tests for share links
Four new tests cover reading a note through its link, sharing a missing note, an unknown token, and a link that stops working after its note is deleted.
Show code
test_app.py 26 assert client.get(f"/notes/{note_id}").status_code == 404 27 28 29def test_share_link_reads_note(client): 30 note_id = client.post("/notes", json={"title": "Recipe", "body": "flour"}).get_json()["id"] 31 shared = client.post(f"/notes/{note_id}/share") 32 assert shared.status_code == 201 33 url = shared.get_json()["url"] 34 assert url.startswith("http://localhost/shared/") 35 opened = client.get(url) 36 assert opened.status_code == 200 37 assert opened.get_json()["body"] == "flour"
test_app.py 45 assert client.get("/shared/not-a-token").status_code == 404 46 47 48def test_share_link_dies_with_note(client): 49 note_id = client.post("/notes", json={"title": "Temp"}).get_json()["id"] 50 url = client.post(f"/notes/{note_id}/share").get_json()["url"] 51 client.delete(f"/notes/{note_id}") 52 assert client.get(url).status_code == 404
Endpoint documentation
The README's endpoint list now includes the share endpoint and the shared-note endpoint, alongside the existing note endpoints.
Show code
README.md 6 .venv/bin/python -m flask --app app run # http://127.0.0.1:5000/notes 7 .venv/bin/python -m pytest -q # tests 8 9Endpoints: `GET /notes`, `POST /notes` (`{"title", "body"}`), `GET /notes/<id>`, `DELETE /notes/<id>`, `POST /notes/<id>/share` (returns `{"token", "url"}`), `GET /shared/<token>`.
What this means
- The link has no expiry or way to cancel it yet. You asked for expiry as a later step, so this is expected.
- The test run reported all seven tests passing. The seven include the four new share tests.
- BuildGist cannot tell who made the edits to the three changed files. They may have been made by you or another tool, not the coding agent.
Concerns
The line that creates each share token is masked in the shown code, so it cannot be checked whether the token is hard to guess, and anyone who guesses one can read the note. Medium
Each share link has a secret code in it. The part of the code that makes that code is hidden in what was shown, so it cannot be confirmed that the code is hard to guess. If it were easy to guess, someone could read notes they were never given.
Show evidence
47 abort(404) 48 return "", 204 49 50 @app.post("/notes/<int:note_id>/share") 51 def share_note(note_id: int): 52 if note_id not in notes: 53 abort(404) 54 token = [redacted]) 55 shares[token] = note_id 56 url = url_for("read_shared_note", token=[redacted], _external=True) 57 return jsonify({"token": token, "url": url}), 201 58
56 url = url_for("read_shared_note", token=[redacted], _external=True) 57 return jsonify({"token": token, "url": url}), 201 58 59 @app.get("/shared/<token>") 60 def read_shared_note(token: str): 61 note = notes.get(shares.get(token)) 62 if note is None: 63 abort(404) 64 return jsonify(note) 65 66 return app
Share tokens are never removed from the shares mapping when their note is deleted, so stale entries accumulate. Low
More
When a note is deleted, its share codes are not cleared out of the lookup table. Reading one of those old links still gives a not-found answer, but the table keeps growing.
Show evidence
10def create_app() -> Flask: 11 app = Flask(__name__) 12 notes: dict[int, dict] = {} 13 shares: dict[str, int] = {} # token -> note id 14 next_id = 1 15 16 @app.get("/notes")
45 assert client.get("/shared/not-a-token").status_code == 404 46 47 48def test_share_link_dies_with_note(client): 49 note_id = client.post("/notes", json={"title": "Temp"}).get_json()["id"] 50 url = client.post(f"/notes/{note_id}/share").get_json()["url"] 51 client.delete(f"/notes/{note_id}") 52 assert client.get(url).status_code == 404