From 7ff9ddd6c2c23d2590098d120ca9751217ebd71c Mon Sep 17 00:00:00 2001 From: eulaly Date: Mon, 18 May 2026 11:06:46 -0400 Subject: [PATCH] docker build testing --- docker-compose.yml | 15 +++++++++++++++ tasks.org | 13 +++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 docker-compose.yml diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..f30c25c --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,15 @@ +services: + synq-server: + build: ./server + container_name: synq-server + restart: unless-stopped + ports: + - "8765:8765" + environment: + PHONE_CAPTURE_TOKEN: "${PHONE_CAPTURE_TOKEN}" + PHONE_CAPTURE_ORG_PATH: "/data/synq.org" + PHONE_CAPTURE_DB_PATH: "/data/capture.sqlite3" + PHONE_CAPTURE_HOST: "0.0.0.0" + PHONE_CAPTURE_PORT: "8765" + volumes: + - /mnt/user/ben/synq/phone-capture:/data diff --git a/tasks.org b/tasks.org index e1933da..ab89836 100644 --- a/tasks.org +++ b/tasks.org @@ -108,8 +108,10 @@ FastAPI app in server/app/main.py. Auth via Bearer token dependency injected on - kind is constrained to note/todo. - body is trimmed and must not be empty. - tags are normalized before formatting. + *** notes Pydantic v2 model in server/app/models.py. Body is stripped via field_validator; kind uses Literal["note","todo"]. Tag normalization lives in org_writer.py so the model stays a plain schema. + *** evidence - commit: e873a00 - tests: pytest tests/test_api.py::TestCapture::test_empty_body_rejected, test_invalid_kind_rejected — pass @@ -123,20 +125,25 @@ Pydantic v2 model in server/app/models.py. Body is stripped via field_validator; - tags are emitted as org heading tags. - multiline note body is preserved. - tests cover todo, note, tags, empty tags, and multiline body. + *** notes Pure function format_capture() in server/app/org_writer.py. Single-line notes: heading is "* note", body below drawer. Multiline notes: heading is "* note: ", full body below drawer. Tag normalization strips #, lowercases, replaces spaces with _, removes non-[a-z0-9_] chars, deduplicates. + *** evidence - commit: e873a00 - tests: pytest tests/test_org_writer.py — 15 tests (7 normalize_tags + 8 format_capture), all pass - datetime: [2026-05-17 Sat 17:00] ** DONE implement sqlite idempotency store + *** acceptance - accepted capture ids are stored. - repeated id returns accepted/already-seen without appending. - db path is configurable. + *** notes IdempotencyStore in server/app/store.py. Uses sqlite3 with a seen_ids table. DB path from PHONE_CAPTURE_DB_PATH env var. already_seen() checks before write; mark_seen() inserts after append. + *** evidence - commit: e873a00 - tests: pytest tests/test_api.py::TestCapture::test_duplicate_capture_returns_already_seen, test_duplicate_not_appended_twice — pass @@ -149,8 +156,10 @@ IdempotencyStore in server/app/store.py. Uses sqlite3 with a seen_ids table. DB - writes utf-8. - appends exactly one entry per new capture. - uses file lock or equivalent simple concurrency guard. + *** notes Append logic in main.py POST /capture handler. Uses a module-level threading.Lock (get_file_lock()) around open(path, "a", encoding="utf-8"). Creates parent dirs if missing. Org path from PHONE_CAPTURE_ORG_PATH env var. + *** evidence - commit: e873a00 - tests: pytest tests/test_api.py::TestCapture::test_valid_capture_appended_to_org, test_duplicate_not_appended_twice — pass @@ -163,8 +172,10 @@ Append logic in main.py POST /capture handler. Uses a module-level threading.Loc - duplicate capture test. - invalid token test. - empty body rejection test. + *** notes 28 tests total across test_api.py (12) and test_org_writer.py (16). All pass. Run with: cd server && python -m pytest tests/ -v + *** evidence - commit: e873a00 - tests: pytest tests/ — 28 passed in 0.33s @@ -176,8 +187,10 @@ Append logic in main.py POST /capture handler. Uses a module-level threading.Loc - compose example maps `/data`. - env vars configure token, org file, and sqlite path. - container starts and exposes configured port. + *** notes server/Dockerfile uses python:3.11-slim, installs deps, copies app/, exposes 8765. docker-compose.example.yml already existed in root with correct env var mapping. CMD runs python -m app.main via uvicorn. + *** evidence - commit: e873a00 - tests: n/a (docker build not run in CI; validate manually with: docker build ./server && docker run -e PHONE_CAPTURE_TOKEN=... -p 8765:8765 -v /data:/data )