Files
synq/docs/server-notes.md
2026-05-17 15:59:43 -04:00

118 lines
1.9 KiB
Markdown

# server notes
## stack
- python
- fastapi
- pydantic
- sqlite
- uvicorn
- pytest
- docker
## env vars
```text
PHONE_CAPTURE_TOKEN=change-me
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
```
## endpoints
- `GET /health`
- `POST /capture`
see `docs/api.md`.
## file writing
server appends to one org file. it does not parse or rewrite existing org content.
recommended append behavior:
- format entry into string ending with newline.
- acquire a process-local lock for append.
- open file in append mode with utf-8.
- write exactly one entry.
- flush/close.
- store capture id in sqlite.
## tag normalization
org heading tags must look like:
```org
:home:errands:
```
normalization:
- lowercase
- trim whitespace
- strip leading `#`
- replace spaces with `_`
- remove chars not matching `[a-z0-9_@#%]` or choose a stricter set
- collapse duplicates
- omit empty tags
## heading rules
todo:
```org
* TODO <first line> :tag:
```
note single-line:
```org
* note: <body> :tag:
```
note multiline:
```org
* note: <first line> :tag:
...
<body preserved below drawer>
```
## auth
use one shared bearer token.
do not add oauth, users, sessions, or accounts.
## docker
bind port on lan only. do not publish via swag/cloudflare.
example:
```yaml
services:
synq:
build: ./server
ports:
- "8765:8765"
environment:
PHONE_CAPTURE_TOKEN: "${PHONE_CAPTURE_TOKEN}"
PHONE_CAPTURE_ORG_PATH: "/data/synq.org"
PHONE_CAPTURE_DB_PATH: "/data/capture.sqlite3"
volumes:
- /mnt/user/mac/synq/phone-capture:/data
```
## tests to write first
- org formatter: todo with tags.
- org formatter: note with no tags.
- org formatter: multiline note.
- api: valid post appends once.
- api: duplicate post appends once.
- api: missing token rejected.
- api: empty body rejected.