mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-24 18:19:05 +02:00
## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work. > - Storage plugins already own project storage and task checkout preparation. > - Core only selected these plugins through an explicit project policy. > - Installation could therefore leave new and existing projects on incompatible Core preparation. > - This pull request adds one generic manifest declaration and one shared effective-policy resolver. > - Project configuration shows inheritance while durable workspace bindings retain their owners. ## Linked Issues or Issue Description **Subsystem affected** Plugin contracts, project configuration, and execution workspace preparation. **Problem or motivation** An installed storage provider cannot become the company default. Projects without an explicit provider keep Core preparation, even when their execution environment cannot use a Core Git checkout. **Proposed solution** A provider declares supported `workspaceProvider.defaultForProjects` mode and strategy. Company-enabled installations supply inherited defaults. Explicit plugin selections and explicit Core/local (`storageProviderPluginId: null`) win. Conflicting defaults require an operator choice. The declaration and implementation contain no provider-specific identifiers. **Alternatives considered** Rewriting every project would lose the distinction between inheritance and overrides. Selecting by worker health would silently change storage on an outage. **Roadmap alignment** Extends the existing workspace and sandbox provider contracts. The roadmap has no duplicate default-provider implementation. Related public work includes #17243, which covers prepared execution directories rather than provider selection. ## What Changed - Add a validated generic default-provider declaration and document it in the SDK. - Resolve provider selection and Git defaults consistently in project responses, source selection, heartbeat source resolution, reservation, and preparation. - Keep stored policy separate from effective configuration. Add the normal project configuration selector for inheritance, explicit plugins, and Core/local. - Preserve existing local and plugin workspace ownership. Pin selection through preparation and keep provider failures visible. - Add database, API, manifest, heartbeat, and UI regressions. Update the verification maps. ## Verification - Targeted Vitest runs cover manifest validation, project defaults and API access, explicit overrides, existing ownership, new/imported task inheritance, heartbeat routing, source-free tasks, selection pinning during setup, and UI configuration. - Combined policy, provider integration, and heartbeat run: 58 tests pass; 60 unrelated cases excluded. After the final shared-provider fallback fix, all 47 policy tests pass, including shared and operator-mode regressions. - Server and UI TypeScript checks, SDK build, verification-map validation, credential-pattern scan, added-comment scan, and `git diff --check` pass. - A downstream integration uses this Core resolver and preparation service with a real storage hook and mocked remote infrastructure. A new Git project reaches the hook without a stored provider ID. - Standard Greptile and Apex both scored 5/5 on5d42998466. All review threads are resolved. - Final GitHub CI is fully green on5d42998466. Browser shard 3 initially hit a PostgreSQL deadlock during cleanup cancellation, which left an experiment flag enabled for a later test. A failed-job retry passed all 26 browser tests. The workflow completed successfully on attempt 2. Full final verification was delegated to CI at the user's request. - No live provider or hosted tenant run was performed. ## Risks - Installing one default-claiming provider changes effective selection for unconfigured projects. Existing explicit settings and workspace ownership remain intact; incompatible explicit settings fail clearly. - Each configuration/admission resolution reads installed plugin metadata and the selected company's enablement. Project list reads share one catalog query. Selection does not call workers or external providers. - Deploy the Core contract before any downstream manifest uses the declaration. No migration or backfill is required. A downstream immutable image pin must include this change before packaging its declaration. - No merge or deployment is authorized by this PR. ## Model Used OpenAI GPT-6 through Codex, with reasoning, repository tools, and code execution. The exact served model ID and context-window size are not exposed in this session. ## 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 described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links - [x] My branch name describes the change and contains no internal ticket id - [x] I have run targeted tests locally and they pass; full gates are delegated to CI at the user's request - [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 on 5d42998466ad42400564ba34f48124f40c53fbc5; the branch has no merge conflicts - [x] Standard Greptile is 5/5 on5d4299846after all fixes, with no unresolved threads - [x] Apex is 5/5 on5d42998466, after standard Greptile 5/5 on that same head - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip <noreply@paperclip.ing>
157 lines
7.7 KiB
Markdown
157 lines
7.7 KiB
Markdown
# Projects and repositories — agent access
|
||
|
||
Product map: [Projects and repositories](../feature-map/projects.md).
|
||
|
||
Feature ID: `projects`.
|
||
|
||
Review date: 2026-10-12. Source commit: `f981fa3cc10cb8663a87dec60345fbff46d54d0a`.
|
||
|
||
This is a source-reviewed baseline of representative operations and known gaps.
|
||
Each capability needs operation-level review before its entire scope can be
|
||
qualified. No live agent execution is claimed. Follow the [map contract](../README.md)
|
||
for format, permission checks, evidence and maintenance.
|
||
|
||
## `lifecycle`
|
||
|
||
Capability ID: `projects/lifecycle`.
|
||
|
||
Review: `baseline`.
|
||
|
||
API: `present` — representative operation IDs:
|
||
|
||
- `POST /api/companies/{companyId}/projects`.
|
||
- `PATCH /api/projects/{id}`.
|
||
- `DELETE /api/projects/{id}`.
|
||
|
||
Agent access: `available` — Native create_project/list_projects; REST / CLI / MCP.
|
||
|
||
Policy: Company/project visibility, protected configuration/runtime policies; some
|
||
repository/privacy management requires board.
|
||
|
||
Evidence: `source-only` — [implementation](../../server/src/routes/projects.ts#L278) at
|
||
the reviewed commit above.
|
||
|
||
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
||
credentials/run context; inspect its result and applicable persistence/attribution.
|
||
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
||
remaining operations before qualifying the whole capability.
|
||
|
||
Gaps: Actual data operations exist; project discovery and private-resource permissions
|
||
still apply.
|
||
|
||
## `task-context`
|
||
|
||
Capability ID: `projects/task-context`.
|
||
|
||
Review: `baseline`.
|
||
|
||
API: `present` — representative operation IDs:
|
||
|
||
- `GET /api/companies/{companyId}/issues`.
|
||
- `POST /api/companies/{companyId}/issues`.
|
||
|
||
Agent access: `available` — Native create_task/search_tasks; REST / CLI / MCP.
|
||
|
||
Policy: Company/project visibility, protected configuration/runtime policies; some
|
||
repository/privacy management requires board.
|
||
|
||
Evidence: `source-only` — [implementation](../../server/src/routes/projects.ts#L278) at
|
||
the reviewed commit above.
|
||
|
||
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
||
credentials/run context; inspect its result and applicable persistence/attribution.
|
||
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
||
remaining operations before qualifying the whole capability.
|
||
|
||
Gaps: Use explicit project context; task creation, assignment, and execution remain
|
||
separate checks.
|
||
|
||
## `repositories`
|
||
|
||
Capability ID: `projects/repositories`.
|
||
|
||
Review: `baseline`.
|
||
|
||
API: `present` — representative operation IDs:
|
||
|
||
- `GET /api/companies/{companyId}/project-repositories`.
|
||
- `PUT /api/projects/{id}/repositories`.
|
||
|
||
Agent access: `partial` — Native list_project_repositories/create_project for initial
|
||
selection; board-only replacement API.
|
||
|
||
Policy: Company/project visibility, protected configuration/runtime policies; some
|
||
repository/privacy management requires board.
|
||
|
||
Evidence: `source-only` — [implementation](../../server/src/routes/projects.ts#L278) at
|
||
the reviewed commit above.
|
||
|
||
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
||
credentials/run context; inspect its result and applicable persistence/attribution.
|
||
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
||
remaining operations before qualifying the whole capability.
|
||
|
||
Gaps: Authorized initial selection works. Replacement of repositories on an existing
|
||
project hard-requires board and needs a delegation decision.
|
||
|
||
## `defaults`
|
||
|
||
Capability ID: `projects/defaults`.
|
||
|
||
Review: `baseline`.
|
||
|
||
API: `present` — representative operation IDs:
|
||
|
||
- `PATCH /api/projects/{id}`.
|
||
- `GET /api/projects/{id}/workspaces`.
|
||
|
||
Agent access: `partial` — REST / native call_api for permitted fields; CLI
|
||
project/workspace.
|
||
|
||
Policy: Company/project visibility, protected configuration/runtime policies; some
|
||
repository/privacy management requires board.
|
||
|
||
Evidence: `source-only` — [implementation](../../server/src/routes/projects.ts#L278) at
|
||
the reviewed commit above.
|
||
|
||
Verification: `not-run` — exercise a listed permitted operation with actual agent
|
||
credentials/run context; inspect its result and applicable persistence/attribution.
|
||
Assert the relevant denied actor, owner, company or mode from Policy. Review the
|
||
remaining operations before qualifying the whole capability.
|
||
|
||
Gaps: Description/goal/target selection exist; host workspace command mutation is denied
|
||
to agents and budget policy is board-managed.
|
||
|
||
Repository attachment also writes a durable skill import binding in its transaction.
|
||
Agent-created bindings derive their refresh person from authenticated responsible-user
|
||
context. Project selection does not grant runtime credentials or override private
|
||
project skill access. Verify automatic import and denial with the actual agent identity.
|
||
|
||
Workspace creation, update and deletion require project:write_workspace through
|
||
the shared authorization evaluator in addition to project read access. Repository
|
||
attachment does not bypass skill-import policy for its background discovery.
|
||
|
||
## `privacy`
|
||
|
||
Capability ID: `projects/privacy`.
|
||
|
||
Review: `baseline`.
|
||
|
||
API: `present` — POST /api/companies/{companyId}/projects; PATCH /api/projects/{id}; GET and POST /api/projects/{id}/access-members; DELETE /api/projects/{id}/access-members/{memberId}. Creation and authorized updates accept visibility; use stable UUID paths for evidence.
|
||
|
||
Agent access: `partial` — authorized agent REST or admitted native `call_api` can create a private project, and eligible project/member reads retain their normal API paths. Existing project visibility and audience mutations require board authority; no dedicated agent audience-management tool is established.
|
||
|
||
Policy: Company access and project:read apply; inaccessible projects return not found. Listing members requires project read, unlike task-grant listing. Visibility/member mutations require a board privacy/personal owner, active company owner/admin, instance admin, or local implicit board. The server derives the creation owner from the board person or agent’s onBehalfOfUserId. Targets must be company agents or active company users; the owner cannot be removed. Agent access intersects agent and responsible-user access. Opening a project does not publish its protected tasks.
|
||
|
||
Evidence: `source-only` — reviewed at `9ef434fe79c57d976b8b03b14c5242db270b8320`. [Project properties](../../ui/src/components/ProjectProperties.tsx), [access members](../../ui/src/components/ProjectAccessMembers.tsx), [project routes](../../server/src/routes/projects.ts), and [authorization](../../server/src/services/authorization.ts).
|
||
|
||
Verification: `not-run` — Verify allowed creation and reads as the actual operator/agent, then compare project and task access after adding/removing a person. Reject ordinary members’ audience changes, agent member/visibility mutations, foreign-company targets, and owner removal. After opening the project, inspect protected tasks and independent direct grants rather than inferring task publication from project discovery.
|
||
|
||
Gaps: The dedicated create_project tool does not advertise a visibility field; explicit private selection uses REST or admitted call_api. Private-project creation through each client, inherited task audiences, and responsible-user combinations need separate live evidence. The map does not infer filesystem isolation from these app-record permissions.
|
||
|
||
Project configuration responses also expose effective workspace storage through
|
||
`workspaceProvider`, separate from the stored execution policy. Existing project
|
||
read/update permissions apply. Omitted provider IDs inherit; null explicitly selects
|
||
Core/local. [Offline API coverage](../../server/src/__tests__/project-workspace-provider.integration.test.ts)
|
||
checks overrides and cross-company denial; live agent credential verification remains unqualified.
|