Schema mirrors the webapp tasks module's ScheduledEvent + EventCompletion
shape:
- tasks.tasks (NIP-52 kind 31922 cache): (pubkey, d_tag) is the
parameterized-replaceable key. JSON-encoded participants / categories
/ recurrence columns are decoded on read via _parse_task_row so each
model can keep clean field validators.
- tasks.completions (kind 31925 cache): unique on
(task_address, pubkey, occurrence). occurrence is NULL for one-shot
tasks; create_completion deletes any prior claim for the same triple
so the latest event wins.
- tasks.settings: singleton row with public_listing toggle.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Empty skeleton mirroring the events extension layout: config/manifest,
pyproject + Makefile + ruff/mypy config, FastAPI routers wired into
tasks_ext, NostrClient bootstrap stubs, and an empty static/routes.json.
Models, migrations, CRUD, Nostr publisher/sync, and the API/template
layers land in follow-up commits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>