updated readme
This commit is contained in:
150
docs/spec.md
Normal file
150
docs/spec.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# Specifications
|
||||
|
||||
## v1 behavior
|
||||
|
||||
the app launches into a focused text box. the user can type immediately.
|
||||
|
||||
controls:
|
||||
|
||||
- note/todo toggle
|
||||
- optional tags field
|
||||
- save
|
||||
- save and close
|
||||
- sync now
|
||||
- small history view showing pending, synced, and failed entries
|
||||
|
||||
each capture has:
|
||||
|
||||
- stable client-generated id
|
||||
- created timestamp with timezone
|
||||
- kind: `note` or `todo`
|
||||
- body text
|
||||
- tags
|
||||
- device name
|
||||
- sync status
|
||||
- optional last error
|
||||
|
||||
## org output
|
||||
|
||||
todo:
|
||||
|
||||
```org
|
||||
* TODO buy printer paper :home:errands:
|
||||
:PROPERTIES:
|
||||
:CREATED: [2026-05-17 sun 14:31]
|
||||
:SOURCE: android
|
||||
:ID: phone-20260517-143122-a8f2
|
||||
:END:
|
||||
```
|
||||
|
||||
note:
|
||||
|
||||
```org
|
||||
* note :retcon:
|
||||
:PROPERTIES:
|
||||
:CREATED: [2026-05-17 sun 14:33]
|
||||
:SOURCE: android
|
||||
:ID: phone-20260517-143322-b91c
|
||||
:END:
|
||||
|
||||
mobile capture should stay dumb and append-only.
|
||||
```
|
||||
|
||||
## server paths
|
||||
|
||||
default container paths:
|
||||
|
||||
```text
|
||||
/data/synq.org
|
||||
/data/capture.sqlite3
|
||||
/data/rejected.log
|
||||
```
|
||||
|
||||
recommended host mapping:
|
||||
|
||||
```text
|
||||
/mnt/user/synq/phone-capture:/data
|
||||
```
|
||||
|
||||
or map `/data/synq.org` directly to wherever the real org file lives. prefer a dedicated capture file first; emacs can include it in agenda later.
|
||||
|
||||
## security model
|
||||
|
||||
v1 is lan-only. bind the service to the host lan and do not expose it through swag/cloudflare/public dns.
|
||||
|
||||
minimum useful controls:
|
||||
|
||||
- shared bearer token in app and server env
|
||||
- server only accepts json
|
||||
- server rejects empty body
|
||||
- server dedupes ids
|
||||
- server writes append-only org
|
||||
- server never edits or parses existing org
|
||||
- docker volume is backed up
|
||||
|
||||
## repo layout
|
||||
|
||||
suggested monorepo:
|
||||
|
||||
```text
|
||||
synq/
|
||||
android/
|
||||
app/
|
||||
server/
|
||||
app/
|
||||
main.py
|
||||
models.py
|
||||
org_writer.py
|
||||
store.py
|
||||
tests/
|
||||
Dockerfile
|
||||
pyproject.toml
|
||||
docs/
|
||||
api.md
|
||||
android-notes.md
|
||||
server-notes.md
|
||||
docker-compose.example.yml
|
||||
.env.example
|
||||
tasks.org
|
||||
README.md
|
||||
```
|
||||
## build order
|
||||
|
||||
1. implement server first using curl tests.
|
||||
2. implement android local capture with room.
|
||||
3. implement manual sync.
|
||||
4. add workmanager opportunistic sync.
|
||||
5. add history screen and resend handling.
|
||||
6. polish launch speed and widget/share-target only after core path works.
|
||||
|
||||
## non-goals
|
||||
- no org parser on android
|
||||
- no agenda on android
|
||||
- no sync provider dependency
|
||||
- no nextcloud file editing
|
||||
- no conflict resolution
|
||||
- no public internet exposure
|
||||
- no ai tagging in v1
|
||||
- no account system in v1
|
||||
|
||||
|
||||
## backup
|
||||
|
||||
### what to back up
|
||||
|
||||
the server writes to one directory (the `/data` volume). back up the whole thing:
|
||||
|
||||
```text
|
||||
/data/synq.org ← the canonical org capture file
|
||||
/data/capture.sqlite3 ← idempotency store (dedup ids)
|
||||
/data/token.txt ← auto-generated token (if not using PHONE_CAPTURE_TOKEN env var)
|
||||
```
|
||||
|
||||
on unraid the host path is whatever you mapped in compose, e.g. `/mnt/user/ben/synq/phone-capture`.
|
||||
|
||||
### restore behavior
|
||||
|
||||
- restore the `/data` volume to a new container and start it. the server will pick up where it left off.
|
||||
- `synq.org` is append-only plain text — it is human-readable and recoverable even without the sqlite db.
|
||||
- if `capture.sqlite3` is lost but `synq.org` is intact, the server will accept re-posted captures that were already in the org file (no dedup). the android app marks them synced either way (`already_seen` or `accepted`), so the only side effect is duplicate org entries for anything re-synced. restore the db from backup to avoid this.
|
||||
- if `token.txt` is lost, delete it and let the server generate a new one on next start, then update the app settings.
|
||||
Reference in New Issue
Block a user