mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-26 18:31:34 +01:00
docs: publish private issue operating model
Document ACL behavior, audited break-glass, accepted aggregate-count disclosure, the trust-agent residual risk, CI leak-surface inventory, and the reviewed enforce rollout. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
23ea12c188
commit
71e7799bc1
3 files changed
+103
-3
No files matched your search
+10
-2
@@ -334,12 +334,20 @@ No Docker or external database is required for this mode.
|
||||
|
||||
`PAPERCLIP_ISSUE_PRIVACY_MODE` controls the canonical opt-in issue/project privacy predicate:
|
||||
|
||||
- `shadow` (default): log structured would-deny decisions but preserve existing reads
|
||||
- `enforce`: return private issues only to implicit principals, issue grantees, or private-project access members; hide private projects from non-members
|
||||
- `enforce` (default): return private issues only to implicit principals, issue grantees, or private-project access members; hide private projects from non-members
|
||||
- `shadow`: log structured would-deny decisions but preserve existing reads; use only for rollout diagnosis
|
||||
- `off`: skip the predicate and shadow logging
|
||||
|
||||
Grant lookups use a five-second cache by default; override it with `PAPERCLIP_ISSUE_PRIVACY_CACHE_TTL_MS` when testing revocation timing.
|
||||
|
||||
The default changed from `shadow` to `enforce` after the P5 shadow-log review. The
|
||||
review ran the privacy authorization and route fixtures in shadow mode, classified
|
||||
every structured `issue privacy would deny read` / `project privacy would deny read`
|
||||
record against the expected non-member probes, and found zero unexpected denials.
|
||||
Keep `shadow` as a temporary diagnostic override; it is not a safe production
|
||||
privacy setting. See [ISSUE-PRIVACY.md](./ISSUE-PRIVACY.md) for the user-facing
|
||||
model, break-glass behavior, and residual risks.
|
||||
|
||||
Issue-bound heartbeat runs inherit the same read predicate through the stored
|
||||
`heartbeat_runs.scope_kind = 'issue'` and `issue_id` binding. Issue deletion
|
||||
nulls the foreign key but preserves the explicit issue scope as a fail-closed
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
# Private tasks and projects
|
||||
|
||||
Paperclip work is company-open by default. A task or project can instead be
|
||||
marked private when its title, discussion, documents, attachments, work
|
||||
products, or agent run traces should be limited to named participants.
|
||||
|
||||
## Who can read private work
|
||||
|
||||
A private task is readable by its responsible user, creating user, current
|
||||
user or agent assignee, active task grantees, and members of its private
|
||||
project. Private children inherit the root task's privacy boundary. Assigning a
|
||||
private task grants the assignee access to that private subtree; the grant stays
|
||||
active until it is explicitly revoked.
|
||||
|
||||
Private projects have a separate access-member list. A task-level grant can
|
||||
expose one task without exposing its containing private project. Direct reads
|
||||
by non-members return `404`, and list, count, search, attention, status-card,
|
||||
activity, run-history, and tree-control surfaces apply the same predicate.
|
||||
Visible blocker and mention edges may show a locked identifier-only stub; they
|
||||
never include the private task's title or content.
|
||||
|
||||
Audit logs remain company-wide because they are the sanctioned oversight path.
|
||||
They contain entity identifiers rather than private task content. Dashboard and
|
||||
sidebar aggregate counts also remain company-wide: they may include private
|
||||
work in totals, but do not expose titles, descriptions, or identifiers. The
|
||||
issue list/count APIs themselves are viewer-filtered.
|
||||
|
||||
## Audited break-glass
|
||||
|
||||
Company owners and admins do not silently inherit private-task access. A normal
|
||||
task detail request still returns `404`. When an owner or admin has a legitimate
|
||||
emergency need, they must deliberately request the task with
|
||||
`?breakGlass=true`.
|
||||
|
||||
Every successful break-glass read writes both:
|
||||
|
||||
- an `issue.break_glass_read` audit row containing the actor, task id, and time;
|
||||
- a warning system notice on the private task so its owners can see that access occurred.
|
||||
|
||||
The flag does not change the canonical read predicate, create a grant, or make
|
||||
future reads implicit. Non-admin members and agents cannot use it.
|
||||
|
||||
## Agent runs and shared-agent residual risk
|
||||
|
||||
Issue-bound run detail, events, transcripts, logs, and workspace operations use
|
||||
the task ACL. Company run lists retain only timing/status/token/cost metadata for
|
||||
non-members so budget oversight continues without exposing task identity or run
|
||||
content.
|
||||
|
||||
> **Residual risk — trusted agents (`trust-agent`).** Paperclip enforces privacy
|
||||
> on reads from the control plane, but an agent that legitimately processes a
|
||||
> private task may write learned content into shared persistent memory, its home
|
||||
> directory, an external tool, or a later public response. V1 deliberately
|
||||
> trusts the agent not to exfiltrate that context. Use isolated execution
|
||||
> workspaces and appropriately trusted agents for sensitive work; task ACLs are
|
||||
> not a sandbox or data-loss-prevention system.
|
||||
|
||||
## Rollout modes
|
||||
|
||||
`PAPERCLIP_ISSUE_PRIVACY_MODE=enforce` is the default. `shadow` records
|
||||
structured would-deny decisions without enforcing them and exists only for
|
||||
rollout diagnosis. `off` disables the task predicate. Operators should not use
|
||||
`shadow` or `off` when private-task confidentiality is required.
|
||||
|
||||
Before the enforce-default flip, the P5 review ran the privacy authorization
|
||||
and route fixtures under shadow mode, matched every would-deny record to an
|
||||
expected non-member probe, and found zero unexpected denials. The regression
|
||||
suite keeps explicit non-member assertions for task lists/counts, search and
|
||||
extract, attention, status cards, activity, runs, tree control, blocker and
|
||||
mention stubs, documents/attachments, and private-project lists.
|
||||
|
||||
## CI leak-test inventory
|
||||
|
||||
The privacy regression gate is part of the normal server Vitest suite. Its
|
||||
surface coverage is intentionally distributed beside the routes and services
|
||||
it protects:
|
||||
|
||||
| Surface | Non-member regression coverage |
|
||||
| --- | --- |
|
||||
| Task detail, list, count, grants, documents, work products | `issue-access-grants-routes.test.ts`, `company-search-service.test.ts` |
|
||||
| Search and machine extract | `company-search-service.test.ts`, `company-search-extract-service.test.ts` |
|
||||
| Attention feed | `attention-service.test.ts` |
|
||||
| Status-card hydrate and dry-run | `status-cards.test.ts` |
|
||||
| Activity stream | `activity-service.test.ts`, `activity-routes.test.ts` |
|
||||
| Run list, live run, detail, transcript, events, logs, operation history | `heartbeat-run-privacy-routes.test.ts` |
|
||||
| Tree holds and tree control | `issue-tree-control-routes.test.ts` |
|
||||
| Blocker and mention identifier-only stubs | `issue-access-grants-routes.test.ts` |
|
||||
| Attachment content | `issue-attachment-routes.test.ts` |
|
||||
| Private-project list and direct read | `projects-list-archived-routes.test.ts` |
|
||||
|
||||
Adding a new task-derived read surface requires a non-member fixture in this
|
||||
gate before the surface can ship.
|
||||
+1
-1
@@ -128,7 +128,7 @@ Paperclip’s core identity is a **control plane for autonomous AI companies**,
|
||||
- Do not make the core product a general chat app. The current product definition is explicitly task/comment-centric and “not a chatbot,” and that boundary is valuable.
|
||||
- Do not build a complete Jira/GitHub replacement. The repo/docs already position Paperclip as organization orchestration, not focused on pull-request review.
|
||||
- Do not build enterprise-grade RBAC first. Paperclip now has authenticated mode, company memberships, instance roles, and permission grants, but fine-grained enterprise governance should remain secondary to the core company control plane.
|
||||
- Do not interpret agent-level privacy flags as a project/issue privacy feature in V1; work visibility stays company-scoped.
|
||||
- Do not interpret agent-profile privacy flags as project/issue privacy. Work remains company-open by default, while explicitly private issues and projects use their own task ACLs.
|
||||
- Do not lead with raw bash logs and transcripts. Default view should be human-readable intent/progress, with raw detail beneath.
|
||||
- Do not force users to understand provider/API-key plumbing unless absolutely necessary. There are active onboarding/auth issues already; friction here is clearly real.
|
||||
|
||||
|
||||
Reference in new issue
Block a user