Operations & Configuration
Tasuku runs as a Cloudflare Worker with D1 and a Durable Object. Configuration and operational scripts live at the repo root; deployments are performed by the maintainer.
Runtime configuration
Section titled “Runtime configuration”wrangler.jsonc— Worker config: themainentry (src/worker.ts, which re-exports theSyncInboxDurable Object), thedurable_objectsbinding + migration, the D1 bindings, thesend_emailbinding (SUPPORT_EMAIL, pinned to a verified destination — ADR-017) + theSUPPORT_RATE_LIMITER, theATTACHMENTSR2 bucket for task file attachments (ADR-019), and the Cron Trigger["* * * * *"]driving both the reminder scan (ADR-015) and the daily completed-task cleanup (spec 038 — see Scheduled jobs). All of these are repeated underenv.staging(named envs are non-inheritable — the recurring footgun) (ADR-011/015/017/019).- Bindings are the only way Worker code reaches external resources (D1, the DO, email, rate limiter, the R2 bucket) — injected via
envat request time (constitution §7.8). - Secrets & vars — secrets (
CLERK_SECRET_KEY,VAPID_PRIVATE_KEY) are set withwrangler secret putper env; non-secret runtimevars(ENVIRONMENT,VAPID_PUBLIC_KEY,VAPID_SUBJECT,SENTRY_DSN,SUPPORT_FROM_ADDRESS) live inwrangler.jsonc. Client-bakedPUBLIC_*(Clerk/VAPID/Sentry DSN) come from.env/.dev.varsat build time..dev.vars*are never committed. The full compile-vs-deploy split is in Configuration & Secrets. - Migrations — forward-only D1 migrations in
src/db/migrations(latest:0016push notifications,0017tags,0018attachments,0019completed-task auto-deletion), applied withdb:migrate:*. A new R2 bucket (tasuku-attachments, and…-staging) must be created once per env before deploying spec 037 (ADR-019). Migration0019(spec 038) is additive —tasks.completed_at(+ index) andusers.auto_delete_completed(default 1) — needs no new binding or secret. - Observability — production errors/traces/logs/metrics go to Sentry (ADR-018); no-ops without a DSN. See Observability.
- Environments — production (
tasuku-db) and an isolatedtasuku-stagingWorker +tasuku-db-staging(spec 020).
Build & local CI
Section titled “Build & local CI”Key package.json scripts:
| Script | Purpose |
|---|---|
dev | astro dev |
build | astro build + service-worker patch (scripts/build-sw.mjs) |
db:migrate:local | apply D1 migrations locally (never --remote from the assistant) |
test / test:e2e | Vitest unit/contract; Playwright E2E |
ci:local | the full local mirror of the CI gates |
npm run ci:local runs install → validate (typecheck/lint/format/test) → build → docs site (build + coverage, spec 022) → supply-chain (SBOM, osv-scanner incl. the docs-site lockfile, npm-audit, gitleaks). It is the single verification the project relies on locally.
Scheduled jobs
Section titled “Scheduled jobs”The single Cron Trigger (["* * * * *"], fired every minute) runs the Worker’s scheduled() handler (src/worker.ts). Two independent jobs run from it, each in its own waitUntil/catch so one failing never affects the other:
- Reminder scan (ADR-015 / spec 029) — every minute; sends closed-app Web Push for due reminders. No-ops when VAPID is unconfigured.
- Completed-task cleanup (spec 038) — gated to run once per UTC day (at 03:00 UTC); soft-deletes Tasks completed more than 30 days ago for users with
auto_delete_completed = 1, cascading to their Steps + My Day entries, then fans aSyncSignalto each affected user (owner ∪ active list members) so removals converge in seconds. Tasks only; never Steps on their own. Runs independently of Web Push (no VAPID requirement).
Operational notes for the cleanup job:
- The 03:00 gate is stateless wall-clock logic (
getUTCHours()/getUTCMinutes()), not a persisted “last run” marker — a missed tick (deploy/outage) simply waits until the next day, which is fine for a 30-day retention window. - The first run after first deploy sweeps 0 rows: pre-existing completed Tasks have
completed_at = NULL(no backfill) and are never auto-swept. A largesweptcount on an early run would be a red flag. - Observability (counts only, no task content):
cleanup.auto.run { swept }per gate-open run;cleanup.manual.run { userId, removed }for the user-triggered cleanup. Watch viawrangler tail. - To verify on a deployed env without waiting for 03:00, drive the manual cleanup (
POST /v1/me/completed-tasks/cleanup) — it exercises the same delete → cascade → tombstone → fan-out path — or temporarily widen the gate in a staging-only build.
Deployment
Section titled “Deployment”- The app Worker is deployed with Wrangler by the maintainer (
wrangler deploy; staging vianpm run deploy:staging). D1 migrations are applied withdb:migrate:*. - The documentation site (this site) is built with
npm run build --prefix docs-siteand deployed by the maintainer as a separate Cloudflare Pages project — independent of the app Worker (ADR-012).
CI-cost discipline
Section titled “CI-cost discipline”The project runs on a hard compute cap. Assistant commits use [ci skip] and git push -o ci.skip, only to non-default, MR-free branches; the maintainer opens merge requests and performs all merges and deploys. ci:local is the only verification the assistant relies on (CONTRIBUTING → “CI cost discipline”).
Supporting tooling (not individual module guides)
Section titled “Supporting tooling (not individual module guides)”Several knowledge-graph communities are tooling/governance rather than runtime modules and are summarized here rather than given their own guides: the GitLab CI pipeline (spec 006), supply-chain scanners (ADR-007), static analysis & code-health gates (opengrep SAST, gitleaks history scan, dependency-cruiser, jscpd, knip — shifted left into git hooks), spec-kit workflow/shell helpers, Renovate config, dependency sets, npm scripts, and the i18n message catalogs (en/de; ADR-008). The repository’s test suites (unit/contract/E2E) are likewise cross-cutting and documented alongside the subsystems they exercise.