Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

Validate ?projectId= references a live project on scoped writes (referential integrity)

Open
#1,301 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
48/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Quiet
Tech stack
typescript
Domain
api, backend

Research direction

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.

Written by the indexing model from the issue text.

Description

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 /projects entry owns.
  • projectId is 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 projectId against projectStore.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 projectId as an error rather than returning an empty set.

Acceptance criteria

  • Creating a scoped entity with a projectId that does not exist is rejected (404).
  • Creating a scoped entity with a soft-deleted projectId is 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 projectId source of truth in CriteriaStore)
Dominant language
TypeScript
Stars
5
Forks
5
Avg merge
4d 13h
Merged PRs (30d)
17

Getting set up

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from microsoft/scope

All issues in microsoft/scope

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.