fix(mana-auth) + chore: rewrite /api/v1/auth/login JWT mint, remove Matrix stack

This commit bundles two unrelated changes that were swept together by an
accidental `git add -A` in another working session. Documented here so the
history reflects what's actually inside.

═══════════════════════════════════════════════════════════════════════
1. fix(mana-auth): /api/v1/auth/login mints JWT via auth.handler instead
   of api.signInEmail
═══════════════════════════════════════════════════════════════════════

Previous attempt (commit 55cc75e7d) tried to fix the broken JWT mint in
/api/v1/auth/login by switching the cookie name from `mana.session_token`
to `__Secure-mana.session_token` for production. That was necessary but
not sufficient: Better Auth's session cookie value isn't just the raw
session token, it's `<token>.<HMAC>` where the HMAC is derived from the
better-auth secret. Reconstructing the cookie from auth.api.signInEmail's
JSON response only gave us the raw token, so /api/auth/token's
get-session middleware still couldn't validate it and the JWT mint kept
silently failing.

Real fix: do the sign-in via auth.handler (the HTTP path) rather than
auth.api.signInEmail (the SDK path). The handler returns a real fetch
Response with a Set-Cookie header containing the fully signed cookie
envelope. We capture that header verbatim and forward it as the cookie
on the /api/auth/token request, which now passes validation and mints
the JWT correctly.

Verified end-to-end on auth.mana.how:

  $ curl -X POST https://auth.mana.how/api/v1/auth/login \
      -d '{"email":"...","password":"..."}'
  {
    "user": {...},
    "token": "<session token>",
    "accessToken": "eyJhbGciOiJFZERTQSI...",   ← real JWT now
    "refreshToken": "<session token>"
  }

Side benefits:
- Email-not-verified path is now handled by checking
  signInResponse.status === 403 directly, no more catching APIError
  with the comment-noted async-stream footgun.
- X-Forwarded-For is forwarded explicitly so Better Auth's rate limiter
  and our security log see the real client IP.
- The leftover catch block now only handles unexpected exceptions
  (network errors etc); the FORBIDDEN-checking logic in it is dead but
  harmless and left in for defense in depth.

═══════════════════════════════════════════════════════════════════════
2. chore: remove the entire self-hosted Matrix stack (Synapse, Element,
   Manalink, mana-matrix-bot)
═══════════════════════════════════════════════════════════════════════

The Matrix subsystem ran parallel to the main Mana product without any
load-bearing integration: the unified web app never imported matrix-js-sdk,
the chat module uses mana-sync (local-first), and mana-matrix-bot's
plugins duplicated features the unified app already ships natively.
Keeping it alive cost a Synapse + Element + matrix-web + bot container
quartet, three Cloudflare routes, an OIDC provider plugin in mana-auth,
and a steady drip of devlog/dependency churn.

Removed:
- apps/matrix (Manalink web + mobile, ~150 files)
- services/mana-matrix-bot (Go bot with ~20 plugins)
- docker/matrix configs (Synapse + Element)
- synapse/element-web/matrix-web/mana-matrix-bot services in
  docker-compose.macmini.yml
- matrix.mana.how/element.mana.how/link.mana.how Cloudflare tunnel routes
- OIDC provider plugin + matrix-synapse trustedClient + matrixUserLinks
  table from mana-auth (oauth_* schema definitions also removed)
- MatrixService import path in mana-media (importFromMatrix endpoint)
- Matrix notification channel in mana-notify (worker, metrics, config,
  channel_type enum, MatrixOptions handler)
- Matrix entries from shared-branding (mana-apps + app-icons),
  notify-client, the i18n bundle, the observatory map, the credits
  app-label list, the landing footer/apps page, the prometheus + alerts
  + promtail tier mappings, and the matrix-related deploy paths in
  cd-macmini.yml + ci.yml

Devlog/manascore/blueprint entries that mention Matrix are left intact
as historical record. The oauth_* + matrix_user_links Postgres tables
stay on existing prod databases — code can no longer write to them, drop
them in a follow-up migration if you want them gone for real.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-08 16:25:55 +02:00
parent 4eb5dfe4a0
commit 8e8b6ac65f
254 changed files with 88 additions and 29437 deletions

View file

@ -24,7 +24,6 @@ on:
type: choice
options:
- all
- matrix-web
- mana-auth
- mana-sync
- mana-media
@ -33,7 +32,6 @@ on:
- mana-crawler
- mana-credits
- mana-search
- mana-matrix-bot
- chat-backend
- chat-web
- todo-backend
@ -59,8 +57,6 @@ env:
PROJECT_DIR: /Users/mana/projects/mana-monorepo
COMPOSE_FILE: docker-compose.macmini.yml
ENV_FILE: .env.macmini
DEPLOY_NOTIFY_ROOM_ID: ${{ secrets.DEPLOY_NOTIFY_ROOM_ID }}
DEPLOY_NOTIFY_BOT_TOKEN: ${{ secrets.DEPLOY_NOTIFY_BOT_TOKEN }}
DOCKER_BUILDKIT: 1
PATH: /usr/local/bin:/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin
@ -73,7 +69,6 @@ jobs:
runs-on: self-hosted
if: github.event_name == 'push'
outputs:
matrix-web: ${{ steps.changes.outputs.matrix-web }}
mana-auth: ${{ steps.changes.outputs.mana-auth }}
mana-sync: ${{ steps.changes.outputs.mana-sync }}
mana-media: ${{ steps.changes.outputs.mana-media }}
@ -98,7 +93,6 @@ jobs:
memoro-server: ${{ steps.changes.outputs.memoro-server }}
memoro-audio-server: ${{ steps.changes.outputs.memoro-audio-server }}
memoro-web: ${{ steps.changes.outputs.memoro-web }}
mana-matrix-bot: ${{ steps.changes.outputs.mana-matrix-bot }}
any-changes: ${{ steps.changes.outputs.any-changes }}
steps:
- name: Check for changes
@ -139,7 +133,6 @@ jobs:
echo "Shared packages changed: $SHARED_CHANGED"
echo ""
check_changes "matrix-web" "apps/matrix/apps/web/" "apps/matrix/packages/"
check_changes "mana-auth" "services/mana-auth/"
check_changes "mana-sync" "services/mana-sync/" "packages/shared-go/"
check_changes "mana-media" "services/mana-media/"
@ -165,12 +158,11 @@ jobs:
check_changes "memoro-server" "apps/memoro/apps/server/" "apps/memoro/packages/"
check_changes "memoro-audio-server" "apps/memoro/apps/audio-server/"
check_changes "memoro-web" "apps/memoro/apps/web/" "apps/memoro/packages/"
check_changes "mana-matrix-bot" "services/mana-matrix-bot/"
check_changes "mana-landing-builder" "services/mana-landing-builder/" "packages/shared-types/" "packages/shared-landing-ui/"
# Check if anything needs deploying
ANY="false"
for svc in matrix-web mana-auth mana-sync mana-media mana-notify mana-api-gateway mana-crawler mana-credits mana-search chat-backend chat-web todo-backend todo-web calendar-backend calendar-web clock-web contacts-backend contacts-web music-backend music-web storage-backend storage-web memoro-server memoro-audio-server memoro-web mana-matrix-bot mana-landing-builder; do
for svc in mana-auth mana-sync mana-media mana-notify mana-api-gateway mana-crawler mana-credits mana-search chat-backend chat-web todo-backend todo-web calendar-backend calendar-web clock-web contacts-backend contacts-web music-backend music-web storage-backend storage-web memoro-server memoro-audio-server memoro-web mana-landing-builder; do
val=$(grep "^$svc=" $GITHUB_OUTPUT | tail -1 | cut -d= -f2)
if [ "$val" == "true" ]; then
ANY="true"
@ -231,7 +223,6 @@ jobs:
fi
else
# Build list from detected changes
if [ "${{ needs.detect-changes.outputs.matrix-web }}" == "true" ]; then SERVICES="$SERVICES matrix-web"; fi
if [ "${{ needs.detect-changes.outputs.mana-auth }}" == "true" ]; then SERVICES="$SERVICES mana-auth"; fi
if [ "${{ needs.detect-changes.outputs.mana-sync }}" == "true" ]; then SERVICES="$SERVICES mana-sync"; fi
if [ "${{ needs.detect-changes.outputs.mana-media }}" == "true" ]; then SERVICES="$SERVICES mana-media"; fi
@ -257,7 +248,6 @@ jobs:
if [ "${{ needs.detect-changes.outputs.memoro-server }}" == "true" ]; then SERVICES="$SERVICES memoro-server"; fi
if [ "${{ needs.detect-changes.outputs.memoro-audio-server }}" == "true" ]; then SERVICES="$SERVICES memoro-audio-server"; fi
if [ "${{ needs.detect-changes.outputs.memoro-web }}" == "true" ]; then SERVICES="$SERVICES memoro-web"; fi
if [ "${{ needs.detect-changes.outputs.mana-matrix-bot }}" == "true" ]; then SERVICES="$SERVICES mana-matrix-bot"; fi
if [ "${{ needs.detect-changes.outputs.mana-landing-builder }}" == "true" ]; then SERVICES="$SERVICES mana-landing-builder"; fi
fi
@ -344,7 +334,6 @@ jobs:
health_url_for() {
case "$1" in
mana-auth) echo "http://localhost:3001/health" ;;
matrix-web) echo "http://localhost:5180/health" ;;
chat-backend) echo "http://localhost:3030/health" ;;
chat-web) echo "http://localhost:5010/health" ;;
todo-backend) echo "http://localhost:3031/health" ;;
@ -371,7 +360,7 @@ jobs:
SERVICES="${{ steps.services.outputs.services }}"
if [ "$DEPLOY_ALL" == "true" ]; then
SERVICES="mana-auth matrix-web chat-backend chat-web todo-backend todo-web calendar-backend calendar-web clock-web contacts-backend contacts-web music-backend music-web storage-backend storage-web memoro-server memoro-audio-server memoro-web"
SERVICES="mana-auth chat-backend chat-web todo-backend todo-web calendar-backend calendar-web clock-web contacts-backend contacts-web music-backend music-web storage-backend storage-web memoro-server memoro-audio-server memoro-web"
fi
HEALTH_RESULTS=""
@ -499,23 +488,8 @@ jobs:
COMMIT_MSG=$(git log -1 --pretty=%s 2>/dev/null | head -c 100)
RUN_URL="https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
MSG="⚠️ **Deploy failed**\n\n**Services:** ${SERVICES}\n**Commit:** ${COMMIT_MSG}\n**By:** ${{ github.actor }}\n**[View logs](${RUN_URL})**"
# Send to Matrix deploy-notifications room via Synapse API
ROOM_ID="${DEPLOY_NOTIFY_ROOM_ID:-}"
BOT_TOKEN="${DEPLOY_NOTIFY_BOT_TOKEN:-}"
if [ -n "$ROOM_ID" ] && [ -n "$BOT_TOKEN" ]; then
TXN_ID="deploy-$(date +%s)"
curl -s -X PUT \
"http://localhost:8008/_matrix/client/v3/rooms/${ROOM_ID}/send/m.room.message/${TXN_ID}" \
-H "Authorization: Bearer ${BOT_TOKEN}" \
-H "Content-Type: application/json" \
-d "{\"msgtype\":\"m.text\",\"body\":\"Deploy failed: ${SERVICES}\",\"format\":\"org.matrix.custom.html\",\"formatted_body\":\"$(echo -e "$MSG" | sed 's/"/\\"/g')\"}" \
|| true
echo "Matrix notification sent"
else
echo "Matrix notification skipped (DEPLOY_NOTIFY_ROOM_ID or DEPLOY_NOTIFY_BOT_TOKEN not set)"
fi
MSG="⚠️ Deploy failed: ${SERVICES} (commit ${COMMIT_MSG} by ${{ github.actor }}) — ${RUN_URL}"
echo "$MSG"
- name: Cleanup old images
if: always()

View file

@ -74,7 +74,6 @@ jobs:
nutriphi-backend: ${{ steps.changes.outputs.nutriphi-backend }}
nutriphi-web: ${{ steps.changes.outputs.nutriphi-web }}
skilltree-web: ${{ steps.changes.outputs.skilltree-web }}
mana-matrix-bot: ${{ steps.changes.outputs.mana-matrix-bot }}
any-changes: ${{ steps.changes.outputs.any-changes }}
steps:
- name: Checkout code
@ -113,7 +112,6 @@ jobs:
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
echo "nutriphi-web=true" >> $GITHUB_OUTPUT
echo "skilltree-web=true" >> $GITHUB_OUTPUT
echo "mana-matrix-bot=true" >> $GITHUB_OUTPUT
echo "any-changes=true" >> $GITHUB_OUTPUT
exit 0
fi
@ -156,7 +154,6 @@ jobs:
echo "nutriphi-backend=true" >> $GITHUB_OUTPUT
echo "nutriphi-web=true" >> $GITHUB_OUTPUT
echo "skilltree-web=true" >> $GITHUB_OUTPUT
echo "mana-matrix-bot=true" >> $GITHUB_OUTPUT
echo "any-changes=true" >> $GITHUB_OUTPUT
exit 0
fi
@ -370,14 +367,6 @@ jobs:
echo "skilltree-web=false" >> $GITHUB_OUTPUT
fi
# mana-matrix-bot (consolidated Go bot)
MANA_MATRIX_BOT_CHANGED=$(check_pattern "services/mana-matrix-bot/")
if [ "$MANA_MATRIX_BOT_CHANGED" == "true" ]; then
echo "mana-matrix-bot=true" >> $GITHUB_OUTPUT
else
echo "mana-matrix-bot=false" >> $GITHUB_OUTPUT
fi
# zitare-backend: REMOVED — migrated to local-first
# Check if any service needs building
@ -1221,38 +1210,5 @@ jobs:
cache-from: type=gha
cache-to: type=gha,mode=max
# ===========================================
# Matrix Bots
# ===========================================
build-mana-matrix-bot:
name: Build mana-matrix-bot (Go)
runs-on: ubuntu-latest
needs: detect-changes
if: needs.detect-changes.outputs.mana-matrix-bot == 'true'
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository_owner }}/mana-matrix-bot
tags: type=raw,value=latest
- uses: docker/build-push-action@v5
with:
context: .
file: services/mana-matrix-bot/Dockerfile
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
cache-from: type=gha
cache-to: type=gha,mode=max
# ===========================================
# Zitare Backend: REMOVED — migrated to local-first