Files
STTracker/docs/plans/001-phase1-sdd/task-16-rulings.md
T
Lucas WintherandClaude Opus 5.5 be04fab098 docs: phase 1 handoff, execution ledger and task reports
Captures the owner's requirements and decisions from the planning
conversation, current branch/worktree state, open tasks 17-19, pending
owner decisions and the controller's rulings so a new agent can resume.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-02 04:53:02 +01:00

4.0 KiB

Task 16: controller rulings (binding, in addition to the brief)

The core API already exists. Read the real signatures in packages/core/src/** (auth, works, matching, entries, engagements, lists, copies, custom-fields, attachments, crypto, export, backup, jobs, registry, connections, sync/{run,changes}) and in packages/plugin-sdk/src/types.ts. Several signatures differ from the original plan text. The code is authoritative.

  1. Placeholder web. If apps/web/index.html doesn't exist, create a minimal placeholder (<!doctype html><title>STTracker</title><div id="root">STTracker is starting…</div>). Task 17 replaces it. Serve it at /* via Bun HTML imports, with /api/* and /ingest/* handled first.

  2. Secrets and connections in API responses:

    • Never return secrets, credentials_enc, token hashes or password hashes.
    • GET sources returns listConnections output and must hide deleted connections, i.e. those with status "paused" and no credentials (Task 9 note).
    • POST sources and PATCH sources/:id pass the plugin manifest from the registry into createConnection/updateConnection.
  3. Running and importing:

    • POST sources/:id/run → enqueue(db, "sync", { connectionId, mode? }, { lockKey: "sync:<id>" }). A null result → 409 conflict with the message "A sync for this source is already queued or running."
    • POST sources/:id/import takes a multipart file and enqueues a sync job whose payload carries { connectionId, file: { name, base64 } }.
    • Size limit: 50 MB → 413 with error code validation.
    • Make sure the sync handler (Task 9's syncHandler) supports file mode. If it doesn't, extend it minimally in packages/core/src/connections.ts (allowed).
  4. Ownership of everything by id. Every :id route verifies ownership through the core function, which throws NotFoundError → 404. For attachments, before storeAttachment verify that entity/entityId belongs to the user (Task 7 deferred this to the API layer). GET attachments/:id serves with Content-Type = the stored mime, plus X-Content-Type-Options: nosniff and Content-Disposition: inline; filename="…" (sanitized).

  5. Error mapping:

    • ValidationError → 400 validation, with field and reason in the message.
    • AuthError → 401 for invalid_credentials/unauthenticated, 403 for forbidden, 400 for invite_required/username_taken/invalid_username.
    • NotFoundError → 404 not_found.
    • ImportError → 400 with its code (409 for account_not_empty and conflict).
    • Anything else → 500 internal, with a generic message; log the detail server-side, never return it.
  6. Security basics:

    • Session cookie per the brief.
    • CSRF: for cookie-authenticated non-GET requests, require the header X-Requested-With: sttracker (the web app sends it; Bearer-token requests are exempt).
    • Login and register are rate-limited in-process: 10 per minute per IP, then 429.
    • All JSON bodies are capped at 1 MB.
  7. Boot (main.ts):

    • createDb(DATABASE_URL) → migrateToLatest → loadPlugins(PLUGIN_DIRS);
    • startWorker(db, { sync: syncHandler(...), backup: backupHandler(...) }) and startScheduler;
    • enqueue a daily backup job (lockKey "backup", runAt the next 03:00 local) and re-enqueue it after each run;
    • SIGTERM/SIGINT → stop the worker and scheduler, then close the DB.
    • The DATA_DIR default ./data, created if missing.
  8. OpenAPI is generated from the route table with zod v4 z.toJSONSchema. Every route appears with method, path and summary, plus the request schema where there is one.

  9. AGENTS.md Commands: after verifying, set Dev to bun --hot apps/server/src/main.ts (needs STTRACKER_SECRET) and a Start command. Update docs/PERMISSIONS.md and the tool permission files (.claude/settings.json, .codex/rules/project.rules, .gemini/settings.json) only with commands you actually ran successfully. Update ARCHITECTURE (apps/server real) and DECISIONS (top: CSRF header, error mapping).