managarten/maerchenzauber/apps/backend/README_CHARACTER_UPDATE_FIX.md
Till-JS e7f5f942f3 chore: initial commit - consolidate 4 projects into monorepo
Projects included:
- maerchenzauber (NestJS backend + Expo mobile + SvelteKit web + Astro landing)
- manacore (Expo mobile + SvelteKit web + Astro landing)
- manadeck (NestJS backend + Expo mobile + SvelteKit web)
- memoro (Expo mobile + SvelteKit web + Astro landing)

This commit preserves the current state before monorepo restructuring.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-22 23:38:24 +01:00

2.7 KiB

Character Update Fix Summary

Problem

The character update endpoint was returning 400 Bad Request with "Unknown error" when updating a character after selecting an image.

Root Causes Found

  1. JWT Token Mismatch (FIXED)

    • The JWT token from mana-core had the wrong kid (key ID) in the header
    • Token had: 5a69feee-bdf2-44bb-8bc2-0348f2041b4c
    • Supabase expected: 5a69feee-bdf2-4542-8814-f48ffaa958b8
    • Solution: The APP_KEY_IDS environment variable in mana-core was updated to the correct value
  2. Redundant User Check (FIXED)

    • The update query was adding .eq('user_id', userId) which was redundant with RLS
    • This could cause issues with how Supabase applies RLS policies
    • Solution: Removed the redundant user_id check from the update query
  3. Error Handling (FIXED)

    • Errors were being swallowed and converted to "Unknown error"
    • Solution: Improved error handling to show actual error messages

Current Status

Authentication is working correctly

  • Token validation succeeds
  • Token has correct kid: 5a69feee-bdf2-4542-8814-f48ffaa958b8
  • Token issuer matches Supabase project: https://dyywxrmonxoiojsjmymc.supabase.co/auth/v1

Database access works

  • Character exists in database
  • RLS policies are properly configured
  • Test endpoint can successfully read and update characters

Testing

To test character update:

  1. Get a fresh token by logging in (tokens expire after 1 hour)
  2. Use the token to update a character:
const TOKEN = 'YOUR_FRESH_TOKEN_HERE';
const CHARACTER_ID = 'd8245e4a-a7a2-4a9b-8540-da8a5d3f4853';

const updateData = {
  imageUrl: 'https://example.com/new-image.jpg',
  imagesData: [{
    url: 'https://example.com/new-image.jpg',
    timestamp: Date.now()
  }]
};

fetch(`http://localhost:3002/character/${CHARACTER_ID}`, {
  method: 'PUT',
  headers: {
    'Authorization': `Bearer ${TOKEN}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify(updateData)
});

Files Modified

  1. /src/character/character.controller.supabase.ts

    • Removed redundant .eq('user_id', userId) from update query
    • Improved error handling and logging
  2. /src/supabase/supabase.provider.ts

    • Ensured proper token handling

Environment Variables Required

In mana-core:

  • APP_KEY_IDS: Must include 6c12c767-1f96-461c-b2df-93d5f9c0f063:5a69feee-bdf2-4542-8814-f48ffaa958b8
  • APP_PROJECT_REFS: Must include 6c12c767-1f96-461c-b2df-93d5f9c0f063:dyywxrmonxoiojsjmymc

In storyteller-backend:

  • MAERCHENZAUBER_SUPABASE_URL: https://dyywxrmonxoiojsjmymc.supabase.co
  • MAERCHENZAUBER_SUPABASE_ANON_KEY: The anon key for the project
  • MAERCHENZAUBER_JWT_SECRET: The JWT secret (for future use if needed)