feat(ST-706): task write tools — update_task_status and update_task_plan
- src/access.ts: shared product/story/task access checks via product ownership or membership - update_task_status accepts lowercase API values, converts to DB enum, rejects unknown values - update_task_plan replaces implementation_plan on a task - Both call requireWriteAccess() so demo accounts get PERMISSION_DENIED before any DB write Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e9d87dd8ff
commit
e3f9476568
4 changed files with 123 additions and 1 deletions
30
src/access.ts
Normal file
30
src/access.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import { prisma } from './prisma.js'
|
||||
|
||||
export async function userCanAccessProduct(productId: string, userId: string): Promise<boolean> {
|
||||
const hit = await prisma.product.findFirst({
|
||||
where: {
|
||||
id: productId,
|
||||
OR: [{ user_id: userId }, { members: { some: { user_id: userId } } }],
|
||||
},
|
||||
select: { id: true },
|
||||
})
|
||||
return Boolean(hit)
|
||||
}
|
||||
|
||||
export async function userCanAccessTask(taskId: string, userId: string): Promise<boolean> {
|
||||
const task = await prisma.task.findUnique({
|
||||
where: { id: taskId },
|
||||
select: { story: { select: { product_id: true } } },
|
||||
})
|
||||
if (!task) return false
|
||||
return userCanAccessProduct(task.story.product_id, userId)
|
||||
}
|
||||
|
||||
export async function userCanAccessStory(storyId: string, userId: string): Promise<boolean> {
|
||||
const story = await prisma.story.findUnique({
|
||||
where: { id: storyId },
|
||||
select: { product_id: true },
|
||||
})
|
||||
if (!story) return false
|
||||
return userCanAccessProduct(story.product_id, userId)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue