fix(memory): scope InsightsRepo operations to userId — M2-001/002 (#290)
Some checks failed
ci/woodpecker/push/ci Pipeline failed
Some checks failed
ci/woodpecker/push/ci Pipeline failed
Co-authored-by: Jason Woltje <jason@diversecanvas.com> Co-committed-by: Jason Woltje <jason@diversecanvas.com>
This commit was merged in pull request #290.
This commit is contained in:
@@ -19,8 +19,11 @@ export function createInsightsRepo(db: Db) {
|
||||
.limit(limit);
|
||||
},
|
||||
|
||||
async findById(id: string): Promise<Insight | undefined> {
|
||||
const rows = await db.select().from(insights).where(eq(insights.id, id));
|
||||
async findById(id: string, userId: string): Promise<Insight | undefined> {
|
||||
const rows = await db
|
||||
.select()
|
||||
.from(insights)
|
||||
.where(and(eq(insights.id, id), eq(insights.userId, userId)));
|
||||
return rows[0];
|
||||
},
|
||||
|
||||
@@ -29,17 +32,24 @@ export function createInsightsRepo(db: Db) {
|
||||
return rows[0]!;
|
||||
},
|
||||
|
||||
async update(id: string, data: Partial<NewInsight>): Promise<Insight | undefined> {
|
||||
async update(
|
||||
id: string,
|
||||
userId: string,
|
||||
data: Partial<NewInsight>,
|
||||
): Promise<Insight | undefined> {
|
||||
const rows = await db
|
||||
.update(insights)
|
||||
.set({ ...data, updatedAt: new Date() })
|
||||
.where(eq(insights.id, id))
|
||||
.where(and(eq(insights.id, id), eq(insights.userId, userId)))
|
||||
.returning();
|
||||
return rows[0];
|
||||
},
|
||||
|
||||
async remove(id: string): Promise<boolean> {
|
||||
const rows = await db.delete(insights).where(eq(insights.id, id)).returning();
|
||||
async remove(id: string, userId: string): Promise<boolean> {
|
||||
const rows = await db
|
||||
.delete(insights)
|
||||
.where(and(eq(insights.id, id), eq(insights.userId, userId)))
|
||||
.returning();
|
||||
return rows.length > 0;
|
||||
},
|
||||
|
||||
@@ -70,8 +80,33 @@ export function createInsightsRepo(db: Db) {
|
||||
|
||||
/**
|
||||
* Decay relevance scores for old insights that haven't been accessed recently.
|
||||
* Scoped to a specific user to prevent cross-user data mutation.
|
||||
*/
|
||||
async decayOldInsights(olderThan: Date, decayFactor = 0.95): Promise<number> {
|
||||
async decayOldInsights(userId: string, olderThan: Date, decayFactor = 0.95): Promise<number> {
|
||||
const result = await db
|
||||
.update(insights)
|
||||
.set({
|
||||
relevanceScore: sql`${insights.relevanceScore} * ${decayFactor}`,
|
||||
decayedAt: new Date(),
|
||||
updatedAt: new Date(),
|
||||
})
|
||||
.where(
|
||||
and(
|
||||
eq(insights.userId, userId),
|
||||
lt(insights.updatedAt, olderThan),
|
||||
sql`${insights.relevanceScore} > 0.1`,
|
||||
),
|
||||
)
|
||||
.returning();
|
||||
return result.length;
|
||||
},
|
||||
|
||||
/**
|
||||
* Decay relevance scores for all users' old insights.
|
||||
* This is a system-level maintenance operation intended for scheduled cron jobs only.
|
||||
* Do NOT expose this through user-facing API endpoints.
|
||||
*/
|
||||
async decayAllInsights(olderThan: Date, decayFactor = 0.95): Promise<number> {
|
||||
const result = await db
|
||||
.update(insights)
|
||||
.set({
|
||||
|
||||
Reference in New Issue
Block a user