feat: immutable entries + full task logging

Entries now immutable once journal is generated:
- Edit/delete returns ENTRY_IMMUTABLE error if journal exists
- Frontend shows lock message and hides delete button
- Delete Journal button to unlock entries

Task logging now stores full JSON:
- request: full JSON request sent to AI provider
- response: full JSON response from AI provider
- prompt: formatted human-readable prompt

Prompt structure:
1. System prompt
2. Previous diary entries (journals)
3. Today's entries
This commit is contained in:
lotherk
2026-03-26 22:05:52 +00:00
parent 5c217853de
commit 754fea73c6
10 changed files with 197 additions and 98 deletions

View File

@@ -65,6 +65,11 @@ entriesRoutes.put('/:id', async (c) => {
return c.json({ data: null, error: { code: 'NOT_FOUND', message: 'Entry not found' } }, 404);
}
const journal = await prisma.journal.findFirst({ where: { userId, date: existing.date } });
if (journal) {
return c.json({ data: null, error: { code: 'ENTRY_IMMUTABLE', message: 'Cannot edit entry: journal already generated. Delete the journal first.' } }, 400);
}
const entry = await prisma.entry.update({
where: { id },
data: {
@@ -89,6 +94,11 @@ entriesRoutes.delete('/:id', async (c) => {
return c.json({ data: null, error: { code: 'NOT_FOUND', message: 'Entry not found' } }, 404);
}
const journal = await prisma.journal.findFirst({ where: { userId, date: existing.date } });
if (journal) {
return c.json({ data: null, error: { code: 'ENTRY_IMMUTABLE', message: 'Cannot delete entry: journal already generated. Delete the journal first.' } }, 400);
}
await prisma.entry.delete({ where: { id } });
return c.json({ data: { deleted: true }, error: null });