0.1.95 — handshake version fix + Casdoor migration plan + MCP smoke test

MCP smoke test (2026-05-03)

Tested the deployed MCP endpoint at https://notechondria.trance-0.com/mcp/ end-to-end with a real API key (loaded from api-key.env, never echoed):

  • initialize → 200, returns notechondria-mcp 0.1.0 server info.
  • tools/list → 41 tools registered.
  • get_profile → returns the authenticated user's profile.
  • list_notes → returned 21 existing notes.
  • create_note → created note id=48 with title "MCP smoke test note".
  • update_note id=48 → renamed + edited body.
  • delete_note id=48 → returned {"deleted": true}.
  • get_recent_activity → confirmed cleanup landed.

All MCP CRUD operations work. The instructions field shipped in 0.1.90 wasn't on the response because the user's mcp_skill_md is empty, not because of a bug.

Bug: /api/v1/handshake/ returns version "0.0.0" in production

_read_backend_version() looked at one path (BASE_DIR.parent / "VERSION"). Inside the Docker container that resolves to /home/VERSION, but the Dockerfile never copied the file there — so the lookup hit the OSError fallback and returned "0.0.0". The dev machine worked because the repo root is one level up from backend/.

Fix in backend/notechondria/api_views.py:

  • _read_backend_version() now walks four candidate paths:
    • BACKEND_VERSION env var (escape hatch for non-Docker deploys),
    • BASE_DIR.parent / VERSION (dev machine),
    • BASE_DIR.parent.parent / VERSION (Render/Northflank where the project nests one level deeper),
    • /home/VERSION (canonical Docker location), /VERSION (final fallback).
  • New _build_metadata() helper returns {version, commit, build_time, deploy_target} for the handshake. All four fields are safe to expose; values come from env vars deploy scripts can populate. Never include credentials.
  • handshake view now includes "build": {...} alongside the existing version field.

Deployment-side fixes:

  • backend/Dockerfile adds COPY VERSION /home/VERSION.
  • deployment/jenkins/scripts/prepare_env.sh sets BACKEND_VERSION (from the existing PROJECT_VERSION), BACKEND_BUILD_COMMIT (from GIT_COMMIT), BACKEND_BUILD_TIME (UTC now), and BACKEND_DEPLOY_TARGET=jenkins.
  • deployment/render/scripts/render_backend_start.sh and deployment/northflank/scripts/northflank_start.sh export the same four env vars (using RENDER_GIT_COMMIT / NORTHFLANK_GIT_COMMIT respectively).

Verified locally: with BACKEND_BUILD_COMMIT=abc123def456 and BACKEND_DEPLOY_TARGET=unit-test, _build_metadata() returns:

{
  "version": "0.1.94",
  "commit": "abc123def456",
  "build_time": "",
  "deploy_target": "unit-test"
}

After the next deploy, hit https://notechondria.trance-0.com/api/v1/handshake/ and confirm build.version == "0.1.95" and build.commit is the SHA of this round's HEAD commit before assuming subsequent code paths reflect the latest source.

Casdoor migration plan (next major)

The user flagged that on the next major version, in-house auth (registration / email verification / password reset / OAuth login + bind / multi-device session manager) will be replaced by Casdoor. App-level user state stays on creators.Creator; only identity, credentials, and the social-provider plumbing move out.

Survey + phased plan landed in docs/integrations/casdoor-migration.md:

  1. Survey + design doc (DONE this round).
  2. Add Casdoor SDK + JWT-validating DRF authentication class alongside MultiSessionAuthentication (shadow mode).
  3. Flutter Casdoor SDK in notechondria_shared; route launchOAuth / _AuthDialog through Casdoor.
  4. Cutover: disable legacy LoginApiView / RegisterApiView etc.; Session model becomes read-only.
  5. Cleanup: delete every endpoint / serializer / template / helper listed in the survey.

Each phase is independently shippable. Steps 2 and 3 can land in either order; both must land before step 4.

docs/TODO.md gains a top-level ### Auth subsection under ## Backend with the migration item + a paired note that the MCP Bearer ntc_<key> scheme stays app-internal (Casdoor is not in the per-request hot path for MCP).

The doc also calls out the open questions: username migration via a one-shot management command, MCP API key separation, OAuth allow-list centralization (the GOOGLE_AUTHORIZED_REDIRECT_URIS / GITHUB_AUTHORIZED_REDIRECT_URIS env vars added in 0.1.90 become redundant after cutover), and Casdoor email-template branding.

Operator action

After deploying this version:

  1. Hit /api/v1/handshake/ and confirm:
    • version == "0.1.95"
    • build.commit matches your git rev-parse HEAD
    • build.deploy_target is one of jenkins / render / northflank depending on the platform
  2. (Optional) Set BACKEND_BUILD_COMMIT and BACKEND_BUILD_TIME in any deploy that doesn't already source them from a CI env var.

No new env vars are requiredBACKEND_VERSION and BACKEND_BUILD_* are all optional, with sensible fallbacks.

Carryover

  • All of the Casdoor migration phases (this round only landed the survey + plan).
  • Push-side conflict resolution and asset rotation/pruning from 0.1.94 still open.