paperclip/server
Nicky Leach 11273c18d6
feat(server): resolve per-project-authorized referenced-project set for run prep (#10380)
## Thinking Path

> - Paperclip is the control plane for autonomous AI companies
> - Run prep needs to know which referenced projects belong in a run
without breaking company boundaries
> - The anchor project must keep its existing authorization path, while
additional mentioned projects must be checked independently and fail
closed if access is denied or unknown
> - This pull request adds a helper that computes the deduped,
company-scoped referenced-project set for run prep and warns when a
project is rejected
> - It also introduces an off-by-default kill-switch so downstream
consumers can adopt the set safely
> - The benefit is safer multi-project run preparation without widening
access beyond what the run actor is already allowed to read

## Linked Issues or Issue Description

This PR does not rely on a public GitHub issue. The change is
self-contained and follows the feature-request style description below
so reviewers can evaluate it without leaving the PR.

**Problem / motivation**
- Run prep needs to assemble a referenced-project set that includes the
anchor project plus additional @-mentioned projects.
- Additional projects must be authorized independently and rejected
projects must not widen access.
- The result should be safe to merge inertly behind a default-off
kill-switch until downstream consumers opt in.

**Proposed solution**
- Add `resolveRunReferencedProjects(issueId, anchorProjectId, opts)` in
`server/src/services/heartbeat.ts`.
- Compute a deduped company-scoped set with the anchor project first and
additional mentions admitted only after a fail-closed `project:read`
authorization check.
- Drop missing, foreign-company, denied, or errored projects and append
run warnings when they are rejected.
- Keep the feature inert behind a default-off kill-switch until
downstream workspace resolution is wired to consume it.

**Alternatives considered**
- Reusing company membership alone was rejected because it would
over-admit projects and widen access.
- Including all mentioned projects without per-project authorization was
rejected because it would bypass the existing access model.

**Roadmap alignment**
- This is Phase 1 only: the helper is computed but not yet consumed
downstream, so the merge is inert until a later phase turns the flag on.

## What Changed

- Added `resolveRunReferencedProjects(issueId, anchorProjectId, opts)`
in `server/src/services/heartbeat.ts`.
- Enforced company scoping, deduplication, fail-closed authorization,
and warning emission for additional referenced projects.
- Added a configurable cap for the additional referenced-project set.
- Added tests covering allowed, denied, foreign-company, thrown-auth,
dedupe, and overflow cases.
- Added a default-off kill-switch for downstream consumption of the
computed set.

## Verification

- `tsc --noEmit`
- `server/src/__tests__/issues-service.test.ts` now passes 117/117
- `git log --oneline origin/master..HEAD` shows only the expected single
commit on this branch

## Risks

- The new helper is computed but not yet consumed by workspace
resolution, so behavior only changes once downstream code is wired to
it.
- The authorization path for additional referenced projects is stricter
than before, so any unexpected access gap will surface as a dropped
project plus warning.

## Model Used

OpenAI Codex, GPT-5, tool-use enabled, 128k context.

## Checklist

- [x] I have included a thinking path that traces from project context
to this change
- [x] I have specified the model used (with version and capability
details)
- [x] I have checked ROADMAP.md and confirmed this PR does not duplicate
planned core work
- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] I have either (a) linked existing issues with `Fixes: #` /
`Closes: #` / `Refs: #` OR (b) described the issue in-PR following the
relevant issue template
- [x] I have not referenced internal/instance-local Paperclip issues or
links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip`
URLs)
- [x] My branch name describes the change (e.g. `docs/...`, `fix/...`)
and contains no internal Paperclip ticket id or instance-derived details
- [x] I have run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] All Paperclip CI gates are green
- [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-07-29 09:48:54 -07:00
..
scripts fix(server): use stable tsx/cli entry point in dev-watch 2026-03-28 06:42:03 +07:00
src feat(server): resolve per-project-authorized referenced-project set for run prep (#10380) 2026-07-29 09:48:54 -07:00
CHANGELOG.md chore: release v0.3.1 2026-03-12 13:09:22 -05:00
package.json build(deps-dev): bump @types/node from 22.19.21 to 22.20.1 (#10304) 2026-07-28 10:48:45 -07:00
tsconfig.json Fix root TypeScript solution config 2026-03-09 14:09:30 -05:00
vitest.config.ts fix(test): stop flaky server-suite afterAll hook timeouts (#10024) 2026-07-22 11:51:30 -07:00