Files
PaperClipAI/doc/DEPLOYMENT-MODES.md
T
Melbin J Paulose 47bd4d4803 docs: point section 11 at the renamed implementation plan (#11677)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The `doc/` tree is how a contributor learns the system
> - Section 11 of `doc/DEPLOYMENT-MODES.md` is a map to the other
documents
> - One entry on that map points at a file that is not there
> - Commit `9c7d9ded1` moved every plan into `doc/plans/` with a date
prefix, and this link kept the old name
> - This pull request updates the link to the current file name
> - The benefit is that a reader who follows the map arrives at the plan

## Linked Issues or Issue Description

No issue exists. The problem is below.

**Issue type**

Docs. A link points at a file name that changed.

**Where is the issue?**

`doc/DEPLOYMENT-MODES.md`, line 176, in section 11 "Relationship to
Other Docs".

**What's wrong?**

The line reads:

```
- implementation plan: `doc/plans/deployment-auth-mode-consolidation.md`
```

That file is not in the repository. Commit `9c7d9ded1` ("docs: organize
plans into doc/plans
with date prefixes") renamed it to
`doc/plans/2026-02-23-deployment-auth-mode-consolidation.md`.
The renamed file is there today. The link text was not updated.

The other four entries in section 11 are correct. I checked each one:
`doc/SPEC-implementation.md`, `doc/DEVELOPING.md`, `doc/CLI.md` and
`doc/spec/invite-flow.md`
all exist.

**Suggested fix**

Use the new file name in the link. That is what this pull request does.

## What Changed

- `doc/DEPLOYMENT-MODES.md` line 176 now names
`doc/plans/2026-02-23-deployment-auth-mode-consolidation.md`

## Verification

Run this command. It prints the file, so the new name is correct:

```
ls doc/plans/2026-02-23-deployment-auth-mode-consolidation.md
```

Run this command. It prints nothing, so the old name is wrong:

```
ls doc/plans/deployment-auth-mode-consolidation.md
```

## Risks

Low risk. The change is one file name in one line of documentation. No
code changes.

## Model Used

Claude (Anthropic), model ID `claude-opus-5`, 1M context window,
extended thinking, with tool
use and code execution.

The path was found by [docproof](https://github.com/melbinjp/docproof),
an open source
checker that compares what documentation claims against what the
repository contains. A
person then read the document, checked the rename in `git log`, and
confirmed the other four
links in the same section.

## 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
- [ ] 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

One box stays unticked and I would rather say so than tick it. I did not
run the test suite
locally, because the change is one line of prose and no test reads it.

The other two were unticked when this opened, because CI and Greptile
had not run yet. Both
have now. **29 checks pass and 2 report `skipping`** (Contributor trust,
Storybook visual
regression); none fail. Greptile returned **5/5** with no P2s: *"The
documentation-only change
appears safe to merge. The new path exists ... and replaces an obsolete
path that no longer
exists."*
2026-08-28 11:21:19 -05:00

6.6 KiB

Deployment Modes

Status: Canonical deployment and auth mode model
Date: 2026-02-23

1. Purpose

Paperclip supports two runtime modes:

  1. local_trusted
  2. authenticated

authenticated supports two exposure policies:

  1. private
  2. public

This keeps one authenticated auth stack while still separating low-friction private-network defaults from internet-facing hardening requirements.

Paperclip now treats bind as a separate concern from auth:

  • auth model: local_trusted vs authenticated, plus private/public
  • reachability model: server.bind = loopback | lan | tailnet | custom

2. Canonical Model

Runtime Mode Exposure Human auth Primary use
local_trusted n/a No login required Single-operator local machine workflow
authenticated private Login required Private-network access (for example Tailscale/VPN/LAN)
authenticated public Login required Internet-facing/cloud deployment

Reachability Model

Bind Meaning Typical use
loopback Listen on localhost only default local usage, reverse-proxy deployments
lan Listen on all interfaces (0.0.0.0) LAN/VPN/private-network access
tailnet Listen on a detected Tailscale IP Tailscale-only access
custom Listen on an explicit host/IP advanced interface-specific setups

3. Security Policy

local_trusted

  • loopback-only host binding
  • no human login flow
  • optimized for fastest local startup

authenticated + private

  • login required
  • low-friction URL handling (auto base URL mode)
  • private-host trust policy required
  • Better Auth request rate limiting is off by default for private mode to keep local/LAN repair loops from locking out the operator; set PAPERCLIP_AUTH_RATE_LIMIT_ENABLED=true to opt in
  • bind can be loopback, lan, tailnet, or custom

authenticated + public

  • login required
  • explicit public URL required
  • stricter deployment checks and failures in doctor
  • Better Auth request rate limiting is on by default; set PAPERCLIP_AUTH_RATE_LIMIT_ENABLED=false only when an explicit front-door limiter covers the deployment
  • recommended bind is loopback behind a reverse proxy; direct lan/custom is advanced
  • local stdio MCP runtime slots fail closed by default; set PAPERCLIP_TRUSTED_MCP_RUNTIME_HOST only when a trusted worker/runtime host is configured to supervise those processes. Remote HTTP MCP remains the preferred public-hosted path.

4. Onboarding UX Contract

Default onboarding remains interactive and flagless:

pnpm paperclipai onboard

Server prompt behavior:

  1. quickstart --yes defaults to server.bind=loopback and therefore local_trusted/private
  2. advanced server setup asks reachability first:
  • Trusted local → bind=loopback, local_trusted/private
  • Private network → bind=lan, authenticated/private
  • Tailnet → bind=tailnet, authenticated/private
  • Custom → manual mode/exposure/host entry
  1. raw host entry is only required for the Custom path
  2. explicit public URL is only required for authenticated + public

Examples:

pnpm paperclipai onboard --yes
npx paperclipai onboard --yes --bind lan
npx paperclipai run --bind tailnet

configure --section server follows the same interactive behavior.

5. Doctor UX Contract

Default doctor remains flagless:

pnpm paperclipai doctor

Doctor reads configured mode/exposure and applies mode-aware checks. Optional override flags are secondary.

6. Board/User Integration Contract

Board identity must be represented by a real DB user principal for user-based features to work consistently.

Required integration points:

  • real user row in authUsers for Board identity
  • instance_user_roles entry for Board admin authority
  • company_memberships integration for user-level task assignment and access

This is required because user assignment paths validate active membership for assigneeUserId.

7. Local Trusted -> Authenticated Claim Flow

When running authenticated mode, if the only instance admin is local-board, Paperclip emits a startup warning with a one-time high-entropy claim URL.

  • URL format: /board-claim/<token>?code=<code>
  • intended use: signed-in human claims board ownership
  • claim action:
    • promotes current signed-in user to instance_admin
    • demotes local-board admin role
    • ensures active owner membership for the claiming user across existing companies

This prevents lockout when a user migrates from long-running local trusted usage to authenticated mode.

8. First Admin Setup For Fresh Authenticated Installs

Fresh authenticated installs start in bootstrap_pending until the first instance_admin exists.

For authenticated/private, Paperclip supports a browser-first setup path:

  1. open the Paperclip URL from the private network or appliance UI
  2. sign in or create a Paperclip account
  3. choose Claim this instance on the setup screen

That browser claim promotes the signed-in session user to the first instance admin and then falls through to normal onboarding. The endpoint is available only to real browser session actors in authenticated/private; unauthenticated requests, agent keys, board API keys, and local implicit board actors are rejected.

The CLI fallback remains supported in all authenticated setup states:

pnpm paperclipai auth bootstrap-ceo

That command prints a one-time first-admin invite URL. Browser claim and bootstrap invite acceptance share the same first-admin transaction, so whichever path wins first makes later attempts return a conflict.

For authenticated/public, browser first-admin claim is intentionally disabled. Public deployments must use the high-entropy bootstrap invite path unless a future public-hosted setup design explicitly changes this policy.

9. Current Code Reality (As Of 2026-02-23)

  • runtime values are local_trusted | authenticated
  • authenticated uses Better Auth sessions and bootstrap invite flow
  • local_trusted ensures a real local Board user principal in authUsers with instance_user_roles admin access
  • company creation ensures creator membership in company_memberships so user assignment/access flows remain consistent

10. Naming and Compatibility Policy

  • canonical naming is local_trusted and authenticated with private/public exposure
  • no long-term compatibility alias layer for discarded naming variants

11. Relationship to Other Docs

  • implementation plan: doc/plans/2026-02-23-deployment-auth-mode-consolidation.md
  • V1 contract: doc/SPEC-implementation.md
  • operator workflows: doc/DEVELOPING.md and doc/CLI.md
  • invite/join state map: doc/spec/invite-flow.md