diff --git a/doc/PRODUCT.md b/doc/PRODUCT.md index 90e18b9c..a180efc0 100644 --- a/doc/PRODUCT.md +++ b/doc/PRODUCT.md @@ -9,6 +9,7 @@ Paperclip is the control plane for autonomous AI companies. One instance of Pape ### Company A company has: + - A **goal** — the reason it exists ("Create the #1 AI note-taking app that does $1M MRR within 3 months") - **Employees** — every employee is an AI agent - **Org structure** — who reports to whom @@ -20,6 +21,7 @@ A company has: Every employee is an agent. When you create a company, you start by defining the CEO, then build out from there. Each employee has: + - **Adapter type + config** — how this agent runs and what defines its identity/behavior. This is adapter-specific (e.g., an OpenClaw agent might use SOUL.md and HEARTBEAT.md files; a Claude Code agent might use CLAUDE.md; a bare script might use CLI args). Paperclip doesn't prescribe the format — the adapter does. - **Role & reporting** — their title, who they report to, who reports to them - **Capabilities description** — a short paragraph on what this agent does and when they're relevant (helps other agents discover who can help with what) @@ -80,6 +82,13 @@ More detailed task structure TBD. 6. Set budgets, define initial strategic tasks 7. Hit go — agents start their heartbeats and the company runs +## Guidelines + +There are two deployment scenarios that need to be maintained: + +- a single user, local trusted deployment - this should be easy to install with a single `npx paperclip run` command and the environment is trusted and self-contained on a local machine (e.g. local files, agents, embedded db, easy to use) +- multi-user cloud deployment - allows for a hosted deploy (remote deployment, user logins, hosted db, scalable) + ## Further Detail See [SPEC.md](./SPEC.md) for the full technical specification and [TASKS.md](./TASKS.md) for the task management data model. diff --git a/doc/SPEC-implementation.md b/doc/SPEC-implementation.md index 1f9ef2df..e4fcbcab 100644 --- a/doc/SPEC-implementation.md +++ b/doc/SPEC-implementation.md @@ -95,6 +95,9 @@ V1 implementation extends this baseline into a company-centric, governance-aware - Local default: embedded PostgreSQL at `~/.paperclip/instances/default/db` - Optional local prod-like: Docker Postgres - Optional hosted: Supabase/Postgres-compatible +- File/object storage: + - local default: `~/.paperclip/instances/default/data/storage` (`local_disk`) + - cloud: S3-compatible object storage (`s3`) ## 6.3 Background Processing @@ -302,9 +305,32 @@ Operational policy: - `heartbeat_runs(company_id, agent_id, started_at desc)` - `approvals(company_id, status, type)` - `activity_log(company_id, created_at desc)` +- `assets(company_id, created_at desc)` +- `assets(company_id, object_key)` unique +- `issue_attachments(company_id, issue_id)` - `company_secrets(company_id, name)` unique - `company_secret_versions(secret_id, version)` unique +## 7.14 `assets` + `issue_attachments` + +- `assets` stores provider-backed object metadata (not inline bytes): + - `id` uuid pk + - `company_id` uuid fk not null + - `provider` enum/text (`local_disk | s3`) + - `object_key` text not null + - `content_type` text not null + - `byte_size` int not null + - `sha256` text not null + - `original_filename` text null + - `created_by_agent_id` uuid fk null + - `created_by_user_id` uuid/text fk null +- `issue_attachments` links assets to issues/comments: + - `id` uuid pk + - `company_id` uuid fk not null + - `issue_id` uuid fk not null + - `asset_id` uuid fk not null + - `issue_comment_id` uuid fk null + ## 8. State Machines ## 8.1 Agent Status @@ -420,6 +446,10 @@ All endpoints are under `/api` and return JSON. - `POST /issues/:issueId/release` - `POST /issues/:issueId/comments` - `GET /issues/:issueId/comments` +- `POST /companies/:companyId/issues/:issueId/attachments` (multipart upload) +- `GET /issues/:issueId/attachments` +- `GET /attachments/:attachmentId/content` +- `DELETE /attachments/:attachmentId` ### 10.4.1 Atomic Checkout Contract diff --git a/doc/plan/humans-and-permissions.md b/doc/plan/humans-and-permissions.md new file mode 100644 index 00000000..e31ca02c --- /dev/null +++ b/doc/plan/humans-and-permissions.md @@ -0,0 +1,234 @@ +# Humans and Permissions Plan + +Status: Draft +Date: 2026-02-20 +Owner: Server + UI + Shared + DB + +## Goal + +Add first-class human users and permissions while preserving two deployment modes: + +- local trusted single-user mode with no login friction +- cloud-hosted multi-user mode with mandatory authentication and authorization + +## Why this plan + +Current V1 assumptions are centered on one board operator. We now need: + +- multi-human collaboration with per-user permissions +- safe cloud deployment defaults (no accidental loginless production) +- local mode that still feels instant (`npx paperclip run` and go) +- agent-to-human task delegation, including a human inbox + +## Product constraints + +1. Keep company scoping strict for every new table, endpoint, and permission check. +2. Preserve existing control-plane invariants: +- single-assignee task model +- approval gates +- budget hard-stop behavior +- mutation activity logging +3. Keep local mode easy and trusted, but prevent unsafe cloud posture. + +## Deployment modes + +## Mode A: `local_trusted` + +Behavior: + +- no login UI +- browser opens directly into board context +- embedded DB and local storage defaults remain +- a local implicit human actor exists for attribution + +Guardrails: + +- server binds to loopback by default +- refuse startup if mode is `local_trusted` with non-loopback bind, unless explicit `--allow-unsafe-local-network` +- UI shows a persistent "Local trusted mode" badge + +## Mode B: `cloud_hosted` + +Behavior: + +- login required for all human endpoints +- hosted DB and remote deployment supported +- multi-user sessions and role/permission enforcement + +Guardrails: + +- fail startup if auth provider/session config is missing +- fail startup if insecure auth bypass flag is set +- health payload includes mode and auth readiness + +## Auth and actor model + +Unify request actors into a single model: + +- `user` (authenticated human) +- `agent` (API key) +- `local_board_implicit` (local trusted mode only) + +Rules: + +- in `cloud_hosted`, only `user` and `agent` are valid actors +- in `local_trusted`, unauthenticated browser/API requests resolve to `local_board_implicit` +- all mutating actions continue writing `activity_log` with actor type/id + +## Data model additions + +## New tables + +1. `users` +- identity record for human users (email-based) + +2. `company_memberships` +- `company_id`, `user_id`, status, role metadata +- stores effective permissions and optional org scope constraints + +3. `invites` +- `company_id`, invite email, token hash, expires_at, invited_by, revoked_at, accepted_at +- optional default permissions payload at invite time + +4. `user_permission_grants` (or JSON grant blob in membership) +- explicit grants such as `agents:create` +- includes scope payload for chain-of-command limits + +5. `issues` extension +- add `assignee_user_id` nullable +- preserve single-assignee invariant with XOR check: + - exactly zero or one of `assignee_agent_id` / `assignee_user_id` + +## Compatibility + +- existing `created_by_user_id` / `author_user_id` fields remain and become fully active +- agent API key model remains unchanged, still company-scoped + +## Permission model (initial set) + +Core grants: + +1. `agents:create` +2. `users:invite` +3. `users:manage_permissions` +4. `tasks:assign` +5. `tasks:assign_scope` (org-constrained delegation) + +Additional behavioral rules: + +- board-level users can manage all grants +- non-board users can only act within explicit grants +- assignment checks apply to both agent and human assignees + +## Chain-of-command scope design + +Initial approach: + +- represent assignment scope as an allow rule over org hierarchy +- examples: + - `subtree:` (can assign into that manager subtree) + - `exclude:` (cannot assign to protected roles, e.g., CEO) + +Enforcement: + +- resolve target assignee org position +- evaluate allow/deny scope rules before assignment mutation +- return `403` for out-of-scope assignments + +## Invite and signup flow + +1. Authorized user creates invite with email + grants + optional expiry. +2. System sends invite URL containing one-time token. +3. Invitee signs up/logs in. +4. Email on authenticated account must match invite email. +5. Accepting invite creates active `company_membership` and permission grants. +6. Inviter/admin can revoke invite before acceptance. + +Security rules: + +- store invite token hashed at rest +- one-time use token with short expiry +- all invite lifecycle events logged in `activity_log` + +## Human inbox and agent-to-human delegation + +Behavior: + +- agents can assign tasks to humans when policy permits +- humans see assigned tasks in inbox view (including in local trusted mode) +- comment and status transitions follow same issue lifecycle guards + +API additions (proposed): + +- `GET /companies/:companyId/inbox` (human actor scoped to self) +- `POST /companies/:companyId/issues/:issueId/assign-user` +- `POST /companies/:companyId/invites` +- `POST /invites/:token/accept` +- `POST /invites/:inviteId/revoke` +- `GET /companies/:companyId/members` +- `PATCH /companies/:companyId/members/:userId/permissions` + +## Local mode UX policy + +- no login prompt or account setup required +- local implicit board user is auto-provisioned for audit attribution +- invite/multi-user screens can be hidden or marked unavailable in local mode +- if operator wants collaboration, they must switch to `cloud_hosted` + +## Cloud agents in this model + +- cloud agents continue authenticating through `agent_api_keys` +- same-company boundary checks remain mandatory +- agent ability to assign human tasks is permission-gated, not implicit + +## Implementation phases + +## Phase 1: Mode and guardrails + +- add explicit deployment mode config (`local_trusted | cloud_hosted`) +- enforce startup safety checks and health visibility +- implement actor resolution for local implicit board + +## Phase 2: Human identity and memberships + +- add schema + migrations for users/memberships/invites +- wire auth middleware for cloud mode +- add membership lookup and company access checks + +## Phase 3: Permissions and assignment scope + +- add grant model and enforcement helpers +- add chain-of-command scope checks for assignment APIs +- add tests for forbidden assignment (for example, cannot assign to CEO) + +## Phase 4: Invite workflow + +- invite create/send/accept/revoke endpoints +- email-match enforcement and token security +- UI for invite management and membership permissions + +## Phase 5: Human inbox + task assignment updates + +- extend issue assignee model for human users +- inbox API and UI +- agent-to-human assignment flow with policy checks + +## Acceptance criteria + +1. `local_trusted` starts with no login and shows board UI immediately. +2. `cloud_hosted` cannot start without auth configured. +3. No request in `cloud_hosted` can mutate data without authenticated actor. +4. Humans can be invited by email, accepted with matching email, and revoked. +5. Permissions can be granted/revoked per company member. +6. Assignment scope prevents out-of-hierarchy or protected-role assignments. +7. Agents can assign tasks to humans only when allowed. +8. Humans can view assigned tasks in inbox and act on them per permissions. +9. All new mutations are company-scoped and logged in `activity_log`. + +## Open decisions + +1. Auth provider choice for cloud mode (Auth.js vs hosted provider). +2. Whether local mode supports optional login in addition to implicit board. +3. Exact representation of permission grants (normalized table vs JSON schema). +4. Whether a user can belong to multiple companies in initial release. +5. Whether invite email delivery is built-in or webhook/provider integration only.