Validate ?projectId= references a live project on scoped writes (referential integrity)
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 48/100
- issue の種類
- バグ
- 明瞭さ
- おおむね明確
- 活発さ
- 静か
- 技術スタック
- typescript
調査の方向性
Start at apps/api/src/routes/criteria.ts and trace getQueryProjectId through projectStore.get, then compare the same root-create pattern for profiles, prompt-features, mcp-servers, report-templates, skills, extensions, codebases, and requests. Done means nonexistent project IDs are rejected with 404, soft-deleted IDs are rejected with 409 or handled explicitly, and behavior is consistent across all root-create routes.
索引モデルが issue の本文から書いたものです。
説明
Original author: @manekinekko
Context
Surfaced during a data-model review of the per-project data organization work (PR #1241, design #1210).
Scoped write routes resolve the target project from a client-supplied ?projectId= via getQueryProjectId, which only checks that the value is a non-empty string. There is no verification that the id refers to a project that actually exists and is not soft-deleted.
Example: apps/api/src/routes/criteria.ts →
const doc = await getCriteriaStore(projectId).create({ projectId, id, prompt, dependsOn, gates });
The same pattern applies to every root-create route (profiles, criteria, prompt-features, mcp-servers, report-templates, skills, extensions, codebases, requests).
Problem
- A client can create entities under a non-existent or soft-deleted
projectId, producing orphaned rows that no/projectsentry owns. projectIdis stored as a bare string with no foreign-key guarantee, so nothing at the data layer keeps scoped entities pointing at a live project.- Combined with soft-delete being allowed on non-empty projects, data can be created into a project that is already deleted.
Proposed resolution
- On scoped writes (at minimum root-creates), validate the resolved
projectIdagainstprojectStore.get(projectId)(excluding soft-deleted) before writing. - Reject with 404 (unknown project) or 409 (deleted project) instead of silently writing an orphan.
- A small in-process cache keeps this cheap on hot paths.
- Consider whether scoped list/read should likewise treat an unknown/deleted
projectIdas an error rather than returning an empty set.
Acceptance criteria
- Creating a scoped entity with a
projectIdthat does not exist is rejected (404). - Creating a scoped entity with a soft-deleted
projectIdis rejected (409) or otherwise handled explicitly. - Behavior is consistent across all root-create routes.
Related
- PR #1241 — per-project data organization
- Design #1210
- Related review threads on #1241 (fail-open scoped-store default, double
projectIdsource of truth inCriteriaStore)
- 主要言語
- TypeScript
- スター
- 5
- フォーク
- 5
- 平均マージ
- 3日 22時間
- マージ済み PR(30日)
- 22
環境構築
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
microsoft/scope のほかの issue
-
type: worker-update
難易度 1/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
-
type: worker-update
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
type: worker-update
難易度 1/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
author: JaGord documentation good first issue UI
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
メンテナーはふだん 1 日以内に返信
-
author: cedricvidal bug portal
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
メンテナーはふだん 1 日以内に返信
microsoft/scope の issue をすべて見る
似ている issue
-
難易度 1/5 1時間未満 初心者へのやさしさ 78/100
lichess-org/api#678 ·
-
難易度 2/5 1〜3時間 初心者へのやさしさ 84/100
PostHog/posthog.com#20628 ·
メンテナーはふだん 1 日以内に返信
-
bug status:Needs Triage
難易度 1/5 1時間未満 初心者へのやさしさ 92/100
jupyterlab/jupyterlab#19964 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
agentscope-ai/QwenPaw#8064 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
area: notebooks-jupyter bug theme: new notebook frontend
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
posit-dev/positron#16347 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信