Commit Graph
16 Commits
Author SHA1 Message Date
39279aa34f feat(ui): shared error, connectivity and query foundation for disconnects (#15754)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The board reads API data and keeps the current task on screen.
> - A restart or temporary network failure can interrupt those reads.
> - Separate page error handlers can hide cached data or expose raw
server codes.
> - The app needs one connection state, readable error copy and a
consistent read policy.
> - This change provides that foundation and moves affected read
surfaces onto it.
> - The dependent write layer in #17960 preserves edits and submissions
across the same failures.

## Linked Issues or Issue Description

**What happened?**

Temporary API failures could replace loaded content with errors.
Different surfaces handled the same outage differently. Some showed raw
server codes. A successful query to an unrelated service could also
falsely report that Paperclip had recovered.

**Expected behavior**

Keep cached content visible. Show one connection banner during sustained
trouble. Confirm recovery through the Paperclip health probe or its
WebSocket. Retry transient reads and show readable errors for permanent
failures.

**Steps to reproduce**

1. Open a populated task or workspace page.
2. Interrupt API requests with a 503 or a dropped connection.
3. Keep an unrelated external request in flight.
4. Confirm that cached content remains and that the external result
cannot clear the outage.
5. Restore the API and check that reads refresh.

The write layer first merged into this feature branch in #15769 now has
its own dependent PR, #17960. This PR contains the shared foundation and
read changes. Merge this PR first.

## What Changed

- Classify API errors and provide readable error copy, including
non-JSON proxy responses and Retry-After handling.
- Use one connection store and health probe with bounded backoff.
Confirm recovery from the server health probe or live-updates WebSocket.
- Pause reads while disconnected, retry transient errors, and refresh
active reads after recovery.
- Keep cached data visible through shared query views and affected page,
panel and plugin read surfaces.
- Add one app-level connection banner and support the pending-write
count consumed by the dependent write layer.
- Add a query-error rendering guard. Call it directly from the existing
CI step. Update development documentation.

## Verification

- Historical-chat lookup now follows the same ready/stale roster state
as rendering. Three regressions fail before the fix; the six new cases
pass after it, including working Retry, fresh data, no-cache error,
permanent 403 and company isolation. All six focused query/recovery
suites pass 200 tests. Final-commit CI passes and Apex is 5/5 with no
unresolved findings. Canary Dry Run initially refused a preview version
that was already on npm. It passed after one rerun with fresh registry
metadata; no check was disabled.

- Integrated current master and retained both transcript interest
registration and connectivity reporting on socket open. The seven
focused recovery/query suites pass 288 tests, and UI typecheck and
production build pass. All 9,451 UI tests across 799 files pass on the
merge commit. Final-commit CI passes and Apex is 5/5 with no unresolved
findings.

- Current head `70d9335d732219352ef0f98414439766bbcb33df`: all hosted CI
checks pass. Apex is **5/5** on that head with no unresolved findings.
The branch has no merge conflict. GitHub still requires code-owner
approval.

- The foundation passes 9,430 UI tests in 804 files. After integrating
current master page paths, 190 focused page tests pass.
- Two unrelated-success regressions fail before the latest fix. With the
fix, 62 focused UI tests, all six guard tests and UI TypeScript pass.
- The composed foundation and write layer pass **9,505 UI tests in 808
files**, UI TypeScript, a production UI build, and query-error, token
and map guards.
- A real Chromium journey on the composed source injects a 503 during
title save. The loaded task stays visible; one reconnect banner appears;
the edit saves after recovery; another task stays unchanged; the saved
title survives reload.
- Full recursive local checks were not repeated because Runner
compilation exhausted local disk during another repair. Hosted checks
must pass before merge. No new staging deployment is claimed.

- Latest review follow-up: a cached CaseDetail now survives a failed
HTTP 429 refresh. Its page regression fails before the fix and passes
after it. Eighty focused foundation tests, UI TypeScript, build and
guards pass after that change.
- Earlier CI evidence is retained: several foundation jobs received a
runner shutdown signal together. The write-layer head also failed an
unchanged Runner descriptor close test with `provider_transport_failed`.
The same Runner source passed that suite in the foundation run. New CI
runs cover the updated heads; no check or assertion was weakened.

## Risks

- Shared retry defaults change the time before transient read errors
appear. Permanent errors still fail promptly.
- ApiError.message now contains readable copy. Callers that compare raw
codes must use ApiError.code.
- Cache success can come from another service or local data. It must not
confirm Paperclip recovery.
- Durable writes are reviewed separately in #17960. This PR does not
change database or mutation contracts.

## Model Used

Anthropic Claude Opus 5.5 (`claude-opus-5-5`) produced the original work
with tool use. OpenAI Codex, GPT-6 family, assisted with restoration,
integration, tests and review fixes. The Codex session does not expose
its exact serving model ID or context window size.

## 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: devinfoley <139239+devinfoley@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Amy (Opus) <claude@users.noreply.github.com>
2026-10-27 21:22:07 -07:00
Devin FoleyandPaperclip 202c2d307e fix(server): leave unclaimed warm Cloud databases idle (#15314)
## Thinking Path

> - Paperclip manages work performed by AI agents.
> - Managed deployments prepare empty applications before an owner
claims them.
> - Those applications start database pollers even though no company can
have work.
> - Health probes also query SQL, so idle databases cannot remain
suspended.
> - This pull request adds an explicit standby marker for empty,
unclaimed Cloud apps.
> - The existing signed, durable claim resumes normal processing without
restarting the app.

## Linked Issues or Issue Description

**What happened?**

An empty, unclaimed warm application runs recurring chat, email, plugin,
heartbeat, cleanup, and reconciliation queries. Its health route also
opens the database. This prevents idle database compute from suspending.

**Expected behavior**

An explicitly marked unclaimed application should keep its HTTP process
and sandbox provider plugins ready while leaving the database idle. A
successful signed claim should resume normal API behavior and background
processing. Claimed and self-hosted instances should keep their current
behavior.

**Steps to reproduce**

Start an empty Cloud-managed application and leave it unclaimed. Observe
database activity while repeatedly requesting `/api/health`. Before this
change, periodic queries continue without company data.

Related: #15153 reduces allocation during chat polling. This change
suppresses polling only for explicitly marked, empty, unclaimed Cloud
apps.

## What Changed

- Add `PAPERCLIP_CLOUD_WARM_STANDBY=1`. Check company emptiness once
after restoring the persisted Cloud runtime identity. Missing Cloud
configuration, existing data, or a persisted claim leaves normal
processing active.
- Gate recurring database pollers with an in-memory predicate. Keep
startup preparation and sandbox provider plugin loading intact.
- Serve unclaimed health probes without session or database reads and
report `warmStandby: true`. Serve standby pages/assets directly from the
UI router, bypassing session, bearer, tenant, and dynamic handlers.
Refuse API requests and all WebSocket upgrades before authentication can
query SQL or seed company data.
- Exit standby after the existing signed identity assertion commits.
Normal timers resume at their next tick; a restart restores the claim
even with stale provider variables.
- Document the marker, readiness semantics, rollout checks, and
rollback.

## Verification

- `pnpm -r typecheck` passed. A final server typecheck also passed after
adding tests.
- `pnpm build` passed.
- Focused standby, signed claim, restart, health, static/Vite routing,
hostname, HMR, and live-events suites: 72 passed after the review fixes.
Includes real HTTP upgrade admission before/after claim.
- `pnpm test:run` was attempted locally; both superseded runs were
stopped after encountering checkout/platform failures. A clean-checkout
rerun eliminated ancestor skill-directory lookup failures. The
company-skills/runtime-cache families encounter macOS
read-only-directory rename failures (`EACCES`); all three company-skills
failures reproduce on unmodified base `bf14f803d5`. The initial full run
also reported one native runner API test failure; an isolated comparison
on both revisions was blocked by local embedded PostgreSQL startup
failures. The full [Linux CI
run](https://github.com/paperclipai/paperclip/actions/runs/37423263993)
passed on final commit `5016c415ea`, including all server and workspace
test shards, browser suites, typecheck, build, and release canary. This
is not a claim that the full local suite passed.
- Isolated full server with local PostgreSQL: after startup and
connection expiry, 70 health probes, 70 page requests carrying valid
synthetic tenant credentials, and 70 rejected WebSocket upgrades over 70
seconds observed zero app database connections. The signed claim
completed in 62 ms and normal polling resumed (475 database transactions
over 12 seconds). Restart with stale provider variables restored the
durable claim. The latency is local-only, not a provider wake
measurement.
- Apex review: **5/5** on `5016c415ea`, both earlier threads resolved,
no open recommendations.
- No live-provider test or production deployment was performed. An
actual database suspension/resume canary remains required before
enabling the control-plane switch.

## Risks

- Standby health reports HTTP readiness rather than current database
connectivity. The signed claim still requires a durable database write;
claimed health checks retain the SQL probe and 503 failure behavior.
- Pollers resume at their usual intervals. A suspended database may add
claim latency. Validate the real provider before enabling the marker.
- Startup preparation and sandbox plugins remain loaded. New plugins or
background loops must respect the same standby contract.
- The marker is off by default. Remove it or set it to `0` and restart
to roll back. No schema migration or claimed-workspace inactivity policy
changes.

## Model Used

OpenAI Codex, based on GPT-6. The exact serving snapshot and configured
context-window size are not exposed in this session. Assistance included
source review, TypeScript changes, command execution, and PostgreSQL
tests.

## 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
#` 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 — targeted tests pass; full
local suite limitations are documented above, and full Linux CI is green
- [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-10-06 09:11:25 -07:00
DottaandPaperclip 61b3fd57a6 fix(ui): recover gracefully during server restarts (#14560)
Show a clear reconnecting state during server restarts and retry safe access
checks every five seconds. Preserve open drafts, wait for initial startup
readiness, and keep authentication failures separate from temporary outages.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-29 08:31:05 -05:00
DottaandPaperclip 270afd2fb8 feat(ui): show running commit in staging account menu (#14410)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - The account menu shows the signed-in user's identity.
> - Staging users need to know which server commit is running after a
deploy.
> - The health endpoint already returns that commit, but the menu does
not show it.
> - This pull request adds the short commit below the email on staging
hosts.
> - Users can open the menu to check a deploy without opening deployment
tools.

## Linked Issues or Issue Description

**What existing behavior does this improve?**

The account menu on staging instances.

**Current behavior**

The menu shows the user's name and email. It does not show the running
server commit.

**Proposed behavior**

On `*.staging.paperclip.app`, show `SHA 8751e2d` below the email. Use
the current `/api/health` commit. Show the full SHA on hover and link to
the commit on GitHub. Refresh the health query when the menu opens. Hide
the label on other hosts and when commit metadata is unavailable.

**Reason and benefit**

A user can confirm which commit a staging instance runs after an
automatic deploy.

**Breaking changes**

None. The server already returns the commit field.

Refs #14060 for related account-menu work. This change adds deployment
information only.

## What Changed

- Add the existing health response commit field to the UI type.
- Share the staging host check and a separate health query across both
account-menu variants. A menu refresh failure leaves the access gate
health state unchanged.
- Show a short SHA below the email. Link to the full commit on GitHub
and include the full SHA in its accessible name and hover title.
- Document the staging label and cover staging hosts, other hosts,
missing metadata, refresh on reopen, and request failure isolation.

## Verification

- `pnpm exec vitest run ui/src/components/SidebarAccountMenu.test.tsx` —
24 tests passed.
- `pnpm check:token-gates` — passed.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed. The UI build and typecheck also passed again
after review fixes.
- Full test matrix — passed on the latest commit in
[CI](https://github.com/paperclipai/paperclip/actions/runs/36447810742).
The local `pnpm test:run` was stopped before completion after CI
finished the same suites. The focused local tests, full local typecheck,
and full local build passed.
- Browser shard 6 passed on one rerun. Its first attempt lost part of
the draft text in the existing attachment-receipt reload test. No code
changed for the rerun.
- Rendered the real account menu in a local browser fixture with a
staging hostname condition and mocked health response. Confirmed the SHA
fits below the email in the dark menu.
- Greptile review — 5/5, all review threads resolved.
- Manual check after deployment: open the menu on a staging host and
compare the SHA with `/api/health`. Open the menu again after a deploy
to refresh it. Confirm the label is absent on production and localhost.

## Risks

- Low risk. Each menu opening on staging can make one additional health
request.
- The host check applies to `*.staging.paperclip.app`. Other staging
domains will need an explicit update.
- The label identifies the running server commit. It can briefly show
cached data while the request completes.

## Model Used

OpenAI Codex, GPT-6. The exact model variant and context window are not
exposed in this session. Used code execution, repository inspection, and
browser inspection.

## 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
#123` / `Refs #123` 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-09-28 13:43:30 -05:00
DottaandPaperclip b2acc674be fix: enable isolated subscription login on authenticated self-hosted instances (#13344)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - AI Connections store reusable provider credentials with company and
owner boundaries.
> - Self-hosted instances can require board authentication while running
agents on the local server.
> - The login UI treated those instances as unsupported and displayed
instructions without a command.
> - Removing that restriction must not expose the server operator's
existing CLI account.
> - This pull request enables owner-scoped login attempts and reuses the
existing login UI.
> - Users can connect Codex and Claude subscriptions on an authenticated
self-hosted instance.

## Linked Issues or Issue Description

**What happened?**

On an authenticated self-hosted instance, OpenAI subscription setup
displayed terminal instructions with no command and a disabled Connect
button. Claude also could not complete the local connection flow.

**Expected behavior**

An authorized board user can prepare an isolated sign-in attempt, sign
in on the server, and save the verified account as a Connection. This
must not import another user's or the operator's ambient credentials.

**Steps to reproduce**

Run Paperclip in authenticated mode with a local environment. Open
Connections, choose OpenAI or Anthropic, and select Subscription. The
previous UI never enabled local login preparation.

Related: #13247, #13248, and #10751. This fix preserves the restriction
on remote access to the operator's ambient Claude login.

## What Changed

- Allow company-authorized users to create, check, cancel, and complete
their own isolated local login attempts.
- Keep ambient Claude credential import restricted to the local
operator.
- Support isolated Claude credential files without falling back to the
host account or mutating process-wide environment variables.
- Use Codex device authorization so sign-in does not depend on a browser
callback to the remote server's localhost.
- Gate server-host login on authenticated public deployments unless a
trusted runtime host is configured. Publish the capability through
health so setup shows supported alternatives.
- Read isolated Claude credential files through bounded,
descriptor-bound opens with ownership, permission, and symlink checks.
Try the alternate filename after malformed JSON.
- Reuse shared login instructions and lifecycle hooks in onboarding,
agent setup, and Connections. Show health-query failures explicitly.
- Document authenticated self-hosted behavior and add authorization,
isolation, lifecycle, and UI regression tests.

## Verification

- Passed 71 focused tests across connection routes, credential
isolation, legacy compatibility, the shared login hook, and agent setup.
- Passed 89 onboarding regression tests.
- Passed `pnpm -r typecheck`, `pnpm build`, Storybook build, and `pnpm
check:token-gates`.
- Completed real Codex device authorization and Claude browser
authorization on an authenticated Linux self-hosted instance. Both
accounts were detected automatically and saved as Connected. Both
completed attempt directories were removed.
- These live checks cover login, credential validation, and connection
creation. They do not establish a new model execution or long-running
refresh result.
- Review follow-up: 68 focused checks passed after rerunning one route
socket error; the full route/health rerun passed all 49 tests. The
70-test onboarding suite also passed. Final workspace typecheck,
production build, and Storybook build passed again.
- The broad local run exposed an instance-name assumption in two new
assertions. The fixture now uses an explicit non-default instance, and
all 32 connection tests passed with a different inherited instance name.
The superseded broad run was stopped; this is not a claim that the full
local suite completed. Full CI results will be recorded before merge.

## Risks

- The server must have the provider CLI installed. Users still run the
displayed command on the server that hosts Paperclip.
- Authorization checks must keep login attempts scoped to the company,
owner, provider, and reconnect target. Regression tests cover cross-user
and cross-company access.
- Existing local-trusted Claude behavior stays available. Authenticated
remote users cannot use its ambient import path.
- No database migration, dependency change, agent binding change, or
provider routing change is included.

## Model Used

OpenAI GPT-6 through Codex, with reasoning, code execution, and browser
tools. The runtime does not expose a more specific model version or
context-window size.

## 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
- [ ] 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-09-12 23:06:55 +00:00
DottaandPaperclip 27622c156a fix(ui): recover expired Cloud tenant sessions (#12826)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Paperclip Cloud serves each tenant through a browser session and an
HttpOnly cookie.
> - A parked tenant tab can outlive that tenant session.
> - The active SPA then receives a tenant-session 401 from its API calls
and shows the internal error code.
> - A page reload already enters the secure Cloud document and OIDC
handoff and keeps the requested tenant route.
> - This pull request detects only the two Cloud tenant-session 401
codes and starts that existing handoff once.
> - The benefit is that an expired tenant session recovers without
exposing tokens or showing temporary API errors.

## Linked Issues or Issue Description

**What happened?**

A Paperclip Cloud tenant tab can stay open after its HttpOnly tenant
session expires. The next API request returns `401
tenant_session_required` or `401 tenant_session_invalid`. The SPA shows
the internal error code in the full page or in sidebar data consumers. A
manual page refresh clears the error.

**Expected behavior**

The tenant tab must enter the existing Cloud session handoff when an API
request reports an expired tenant session. The handoff must keep the
current route and query. The UI must not show the internal
tenant-session error code.

**Steps to reproduce**

1. Open a Paperclip Cloud tenant route.
2. Keep the SPA open until the tenant session expires.
3. Let the page make an API request.
4. Observe the tenant-session 401 in the page or sidebar.
5. Refresh the page and observe that the existing Cloud handoff restores
the session.

**Paperclip version or commit**

The problem reproduces on `master` at commit `b5f862376`.

**Deployment mode**

Paperclip Cloud tenant deployment.

## What Changed

- Added one tenant-session recovery coordinator for exact top-level
Cloud error codes.
- Reloaded the top-level document once and shared one pending promise
across concurrent failures.
- Applied recovery before normal error handling in the shared API
client, auth API, and health API.
- Applied the same recovery to direct audit CSV exports and provider
trace downloads.
- Preserved ordinary self-hosted 401 behavior and avoided automatic
mutation replay.
- Added tests for exact detection, concurrent failures, auth-session
behavior, health bootstrap, and direct-fetch behavior.

## Verification

- `pnpm exec vitest run --config vitest.config.ts
src/lib/tenant-session-recovery.test.ts src/api/client.test.ts
src/api/auth.test.ts src/api/health.test.ts src/api/heartbeats.test.ts
src/api/audit.test.ts` from `ui/` — 30 tests passed.
- `pnpm --filter @paperclipai/ui typecheck` — passed.
- `pnpm check:token-gates` — passed.
- `pnpm -r typecheck` — passed.
- `pnpm build` — passed.
- `pnpm test:run` — the changed UI tests passed, but the full local
macOS run also hit existing failures in untouched server worktree and
temporary-path tests.
- GitHub verification — 30 checks passed, no checks failed, and the
Storybook job was intentionally skipped because this PR has no visual
changes.
- Greptile — 5/5 on `fbba29a2f`, with no open findings.

## Risks

- Low risk. Detection requires HTTP 401 and one exact top-level Cloud
error code.
- The recovery promise intentionally stays pending because document
navigation replaces the active SPA.
- If the Paperclip ID session has also expired, the existing Cloud
sign-in flow remains authoritative.
- This change does not modify APIs, cookies, token lifetimes, database
state, or Cloud server code.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI GPT-5 Codex. The agent runtime identifies the model as GPT-5.
The context-window size is not exposed. Reasoning, repository editing,
shell execution, test execution, and GitHub CLI tool use were enabled.

## 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-09-04 07:29:14 -05:00
Devin Foley db4defdfbf feat: operator-configurable settings visibility via PAPERCLIP_HIDDEN_SETTINGS (#11823)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The instance settings surface (Access, Plugins, Adapters, General,
Experimental) assumes the person at the keyboard operates the whole
instance
> - Operators who host Paperclip for others — a managed cloud or an
internal shared server — expose settings pages and toggles that do not
apply to their deployment, and the related mutation APIs stay open
> - A hosted tenant can open Plugins or Adapters, try an action, and hit
a confusing failure, because only a few hardcoded platform floors exist
> - This pull request adds a generic, operator-configured visibility
mechanism: one env var hides declared settings surfaces in the UI and
floors their mutation routes with a stable 403 code
> - The benefit is a clean hosted-tenant settings surface for any
operator, with zero behavior change for normal self-hosted instances

## Linked Issues or Issue Description

**Subsystem affected**

Instance settings (server routes and UI), the shared settings registry
in `packages/shared`, and the `/api/health` bootstrap payload.

**Problem or motivation**

An operator who hosts Paperclip for other people cannot hide settings
surfaces that the platform manages. Tenants see Access, Plugins, and
Adapters pages, backup retention, and host-level experimental toggles
that do nothing useful for them. The mutation APIs behind these surfaces
also stay open, so a tenant admin can attempt actions the platform must
control. ROADMAP.md names a cleaner shared deployment story as a goal
("Teams should be able to run the same product in hosted or semi-hosted
environments without changing the mental model").

**Proposed solution**

Add a declarative registry of hideable settings surfaces and one env
var, `PAPERCLIP_HIDDEN_SETTINGS`. The server parses the list at boot,
reports it on `/api/health`, and rejects value-changing writes to hidden
surfaces with a stable `settings_operator_managed` 403 code. The UI
reads the list from the health payload and removes the hidden pages,
sections, and toggles from navigation, routes, and page content. Unknown
keys warn and are ignored, so one list can roll across a fleet with
mixed app versions. With the variable unset, behavior is byte-identical
to today.

**Alternatives considered**

- Hardcode the hidden set for cloud instances in this repo: rejected,
because each hosting operator needs a different policy, and policy does
not belong in shared code.
- Deliver the hidden set through the managed-config document: rejected,
because that channel is cloud-specific and fail-closed on unknown
fields; a plain env var works for any operator, including self-hosted
shared servers.
- Lock the controls with a badge instead of hiding them: rejected for
these surfaces, because they are meaningless to tenants, not merely
platform-controlled; the existing managed-overlay lock stays the right
tool for controlled flags.

**Roadmap alignment**

Supports the "shared deployment story" item in ROADMAP.md: hosted and
semi-hosted deployments keep the same product with a settings surface
that matches what the tenant can actually do.

## What Changed

- New `packages/shared/src/settings-visibility.ts`: registry of hideable
surfaces (every instance settings page — profile, environments, access,
heartbeats, experimental, plugins, adapters; every Instance → General
section; every experimental flag as `instance.experimental.<key>`), the
`PAPERCLIP_HIDDEN_SETTINGS` parser, and the `settings_operator_managed`
error code. The General page stays visible as the settings root and
redirect target.
- New `server/src/services/settings-visibility.ts`: parse-once accessor;
unknown keys log one warning and are ignored.
- `/api/health` reports `hiddenSettings` on every response shape; the
field is omitted when nothing is hidden.
- Server floors on hidden surfaces, with same-value echo tolerance (the
`executionMode` precedent): field-backed general sections and
experimental keys reject value-changing PATCHes, and hiding the whole
Experimental page floors every toggle; plugin lifecycle and config
writes, adapter management writes, and the Access admin routes (reads
included) return 403 `settings_operator_managed`. Reads the app itself
needs (plugin `ui-contributions`, adapter metadata, plugin job trigger)
stay open. Pages without instance-scoped mutation routes are hidden in
the UI only.
- UI: new `useHiddenSettings` hook and `HiddenSettingsPageGate` route
gate (hidden pages redirect to the settings root); the settings sidebar
and tab bar drop hidden entries; remembered settings paths remap to the
default page; `InstanceGeneralSettings` skips hidden sections; every
`ExperimentalToggleCard` now carries its flag key and renders nothing
when hidden.
- Removed the dead `InstanceSidebar` component (referenced only by its
own test).
- Docs: `docs/deploy/environment-variables.md` documents the variable
and the key registry.

## Verification

- `pnpm vitest run` over the new and extended suites: shared registry
and parser, representative floor tests per route class (changed-value
403, same-value echo 200, unset env 200, page-level Experimental
hiding), the health field, the route gate, nav filtering, and
section/card hiding with one hidden example per surface kind — 168 tests
pass.
- Full root `pnpm typecheck` passes.
- Manual: booted a server with the variable set. `/api/health` lists the
keys; an unknown key logs one warning and the server boots; hidden pages
redirect; hidden sections and cards do not render; hidden-field PATCH
returns 403 with `details.code = "settings_operator_managed"`; a
same-value echo returns 200. Unset the variable: the full settings
surface returns and responses are byte-identical to master.

## Risks

- Low risk for self-hosted instances: with the variable unset, the
hidden set is empty, the health field is omitted, and no floor
activates.
- Flooring plugin config writes assumes hosted deployments configure
plugins through the platform. If a future bundled plugin needs
tenant-entered config, the floor needs a narrow carve-out.
- Hidden-key floors tolerate same-value echoes, so API clients that
round-trip full GET responses keep working.
- Hiding a toggle does not change its value; operators pair hiding with
the desired default where the value matters.

## Model Used

Claude Fable 5 (Anthropic, `claude-fable-5`) with extended thinking and
agentic tool use, driven through the Claude Code CLI (file edits, test
execution, and live-server verification loops).

## 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
- [ ] All Paperclip CI gates are green
- [ ] Greptile is 5/5 with no open P2s, recommendations, or follow-ups
- [x] I will address all Greptile and reviewer comments before
requesting merge
2026-08-20 17:54:44 -07:00
DottaandPaperclip 5858ccb981 feat: make in-app features cloud-aware (#10850)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Operators use the same board application in self-hosted and
Paperclip Cloud deployments.
> - A Cloud tenant contains one company, so an in-app company switch
does not change the active Cloud stack.
> - Cloud operators need the sidebar and company surfaces to use the
signed-in user's stack portfolio.
> - The server must derive Cloud identity and links from trusted
instance context instead of client input.
> - This pull request adds canonical Cloud context, a trusted stack
portfolio proxy, and Cloud-aware navigation.
> - The benefit is consistent stack switching on Cloud while self-hosted
company behavior stays unchanged.

## Linked Issues or Issue Description

**Subsystem affected**

Cross-cutting: server REST routes and the React board UI.

**Problem or motivation**

A Cloud-managed instance contains one company. The existing company
switcher could only switch records inside that tenant. It could not move
the operator to another Cloud stack. The existing header also gave long
organization names too little width.

**Proposed solution**

Expose a canonical public Cloud context in health data. Add a trusted
server proxy for the current user's stack portfolio. Use that data in
the board UI to switch stacks with top-level navigation. Keep the
existing company behavior on self-hosted instances. Move search into the
navigation and keep long organization names inside the sidebar panel.

**Alternatives considered**

An in-app `/stacks` route was rejected because Cloud tenant hosts
reserve that path and stack selection must wake or authenticate another
tenant. Client-supplied user identity was rejected because the server
can derive the trusted Cloud actor.

**Roadmap alignment**

This change advances the Cloud deployments milestone. It keeps the
product local-first and Cloud-ready without changing the self-hosted
mental model.

## What Changed

- Added canonical Cloud instance context and public health metadata.
- Added a Cloud-only stack portfolio proxy with trusted actor forwarding
and per-user caching.
- Prevented normal company creation on Cloud-managed instances.
- Switched the sidebar and Companies page from company actions to stack
actions on Cloud.
- Added full-page stack navigation and Cloud create-stack links.
- Moved search into the sidebar navigation so the organization name
keeps more width.
- Added truncation and hover recovery for long organization and stack
names.
- Added server and UI regression coverage for Cloud and self-hosted
behavior.
- Updated the implementation specification for the Cloud contracts.

## Verification

- `node scripts/check-token-gates.mjs` passed. All three token gates are
clean.
- `pnpm --dir server exec vitest run src/__tests__/health.test.ts
src/__tests__/cloud-instance.test.ts src/__tests__/cloud-routes.test.ts
src/__tests__/company-cloud-floor.test.ts
src/__tests__/company-portability-routes.test.ts` passed: 5 files and 66
tests.
- `pnpm --dir ui exec vitest run
src/components/SidebarCompanyMenu.test.tsx` passed: 1 file and 11 tests.
- Pre-PR QA report `7da87ca7` passed all 8 acceptance criteria with real
HTTP route factories and real Chromium screenshots in Cloud and
self-hosted modes.
- Security reviews passed for the canonical Cloud context and stack
portfolio proxy.

## Risks

- Cloud stack switching depends on the configured Cloud application and
tenant portfolio URLs.
- The new health `cloud` block is public by design, but it contains only
canonical public instance metadata.
- The stack proxy fails closed on self-hosted instances and derives the
user identity from the trusted actor.
- Self-hosted navigation and company creation retain their existing
paths and behavior.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, model `gpt-5`. The run used reasoning, repository tools,
shell execution, and GitHub integration. The deployment did not expose
its context-window size.

## 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-08-04 23:00:14 -05:00
Devin Foley 765a75207a Add experimental server info debug view (#8676)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work
> - The dev/server UI exposes a `/api/health` endpoint and a lower-left
account drawer, but nothing surfaces *which* build the running instance
is on or when it last restarted
> - When iterating on a local dev instance it is hard to tell whether
the server you're looking at has actually restarted onto your latest
commit, or how stale the running process is
> - Developers need a lightweight, opt-in way to confirm the running
instance's identity without digging through logs or shelling into the
host
> - This pull request adds an experimental "Server Info Debug View"
setting that surfaces the running instance's last-restart time and
current commit as read-only rows in the account drawer
> - The benefit is a quick, in-UI sanity check of what the live server
is actually running, behind an experimental flag so it ships zero cost
to users who don't opt in

## Linked Issues or Issue Description

No public GitHub issue exists. Describing the underlying request inline
following the feature request template:

**Problem or motivation:**

When working against a local Paperclip dev instance there is no in-UI
way to confirm what the running server is — its current commit or when
it last restarted. You have to check logs or the host shell to know
whether the process picked up your latest build.

**Proposed solution:**

An opt-in experimental setting ("Server Info Debug View") that, once
enabled, renders a small read-only "Server" section at the bottom of the
lower-left account drawer showing **Last restarted** (the server process
start time) and **Running commit** (the current git HEAD short SHA +
subject).

**Alternatives considered:**

A separate top-right pill/overlay (like the work-life-balance plugin).
The account drawer was chosen to reuse existing menu-row styling and
avoid adding new always-present chrome.

**Roadmap alignment:**

Small, self-contained developer-experience aid gated behind an
experimental flag; does not overlap planned core roadmap work.

## What Changed

- Added `server/src/server-info.ts`: captures a `serverInfo` snapshot
once at boot — process start time and current git commit (SHA +
subject). Git is read via `execFileSync` with SHA validation and a
timeout.
- `/api/health` exposes the `serverInfo` snapshot, but only on
full-details health responses (board/agent in authenticated mode, or
local-trusted dev).
- Gated the UI surface behind a new `enableServerInfoDebugView`
experimental setting, wired through the shared instance type, validator,
settings normalizer, and OpenAPI schema.
- UI: added `SidebarServerInfo` rendering the read-only rows in the
account drawer (`BreadcrumbBar` / `SidebarAccountMenu`), plus the
experimental settings toggle and a typed `health` API client.
- Moved `ServerGitInfo` / `ServerInfoSnapshot` into
`@paperclipai/shared` so the server and UI share one definition instead
of duplicating it.
- Added unit tests for the server-info snapshot, health route exposure,
validator/normalizer, settings routes, the experimental settings page,
and the sidebar component.

## Verification

- `pnpm --filter @paperclipai/server exec vitest run
src/__tests__/health.test.ts src/__tests__/server-info.test.ts
src/__tests__/instance-settings-service.test.ts
src/__tests__/instance-settings-routes.test.ts` — 32 passed
- `pnpm --filter @paperclipai/ui exec vitest run
src/components/SidebarServerInfo.test.tsx
src/pages/InstanceExperimentalSettings.test.tsx` — 9 passed
- `tsc --noEmit` on both `@paperclipai/server` and `@paperclipai/ui` —
clean
- Manual: enable **Settings → Experimental → Server Info Debug View**,
refresh the UI, open the lower-left account drawer — a "Server" section
shows Last restarted and Running commit.

## Risks

- Low risk. The UI surface is fully opt-in via an experimental flag and
defaults off.
- The `serverInfo` field on `/api/health` is access-controlled to
full-details responses only (board/agent in authenticated mode, or
local-trusted dev) — never anonymous authenticated callers — so the git
SHA is not broadly exposed.
- The only new server work is a one-time git read at boot, guarded with
SHA validation and a timeout; failures degrade gracefully (the git block
reports `available: false` rather than throwing).

## Model Used

Claude — `claude-opus-4` (Anthropic), extended thinking with tool use,
via Claude Code.

## 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 and contains no
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
2026-06-26 14:47:01 -07:00
DottaandPaperclip f257530537 [codex] UI and dev ops quality-of-life (#6384)
## Thinking Path

> - Paperclip operators spend most of their time scanning the board,
inbox, sidebar, and local dev status surfaces
> - Small UI and dev-ops frictions make repeated operator workflows feel
slower than they need to be
> - The working branch contained several independent quality-of-life
improvements mixed with larger cloud work
> - Grouping these smaller UI/dev-ops changes together keeps review
overhead reasonable without merging them into feature PRs
> - This pull request collects the operator-facing QoL polish into one
standalone branch
> - The benefit is a cleaner board navigation and local dev recovery
experience without depending on cloud upstream sync

## What Changed

- Relaxed forced 44px touch targets for small inline widgets.
- Fixed mobile mention menu scrolling and sidebar spacing on
touch/mobile layouts.
- Synced inbox hover state with j/k selection.
- Moved plugin sidebar entries into the Work section.
- Added manual dev-server restart action/banner behavior.
- Logged plugin bridge 502 causes for better diagnosis.

## Verification

- `pnpm install --frozen-lockfile --ignore-scripts`
- `pnpm --filter @paperclipai/plugin-sdk build`
- `pnpm exec vitest run ui/src/components/MarkdownEditor.test.tsx
ui/src/components/Sidebar.test.tsx
ui/src/components/SidebarProjects.test.tsx ui/src/pages/Inbox.test.tsx
ui/src/components/DevRestartBanner.test.tsx
server/src/__tests__/dev-server-status.test.ts
server/src/__tests__/health-dev-server-token.test.ts
server/src/__tests__/plugin-routes-authz.test.ts` initially failed only
because plugin SDK `dist` was not built in the fresh worktree.
- Rerun after build: `pnpm exec vitest run
server/src/__tests__/plugin-routes-authz.test.ts` passed.
- The remaining targeted UI/dev-server tests passed on the first
post-install run.

## Visual Evidence

- Sidebar layout and plugin Work section: ![Sidebar
desktop](https://raw.githubusercontent.com/paperclipai/paperclip/pap-9861-ui-dev-qol/docs/pr-screenshots/pr-6384/sidebar-desktop.png)
- Inbox/task row selection and hover-state surface: ![Inbox rows
desktop](https://raw.githubusercontent.com/paperclipai/paperclip/pap-9861-ui-dev-qol/docs/pr-screenshots/pr-6384/inbox-rows-desktop.png)
- Dev restart banner desktop: ![Dev restart banner
desktop](https://raw.githubusercontent.com/paperclipai/paperclip/pap-9861-ui-dev-qol/docs/pr-screenshots/pr-6384/dev-restart-banner-desktop.png)
- Dev restart banner mobile: ![Dev restart banner
mobile](https://raw.githubusercontent.com/paperclipai/paperclip/pap-9861-ui-dev-qol/docs/pr-screenshots/pr-6384/dev-restart-banner-mobile.png)

## Risks

- Mostly UI/dev ergonomics with low data risk.
- Sidebar and inbox changes touch frequently used navigation surfaces,
so visual review on desktop/mobile is still useful.

> For core feature work, check [`ROADMAP.md`](ROADMAP.md) first and
discuss it in `#dev` before opening the PR. Feature PRs that overlap
with planned core work may need to be redirected — check the roadmap
first. See `CONTRIBUTING.md`.

## Model Used

- OpenAI Codex, GPT-5-based coding agent with local shell/git/tool use.
Exact hosted model ID and context-window size are not exposed by the
local Paperclip adapter runtime.

## 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 run tests locally and they pass
- [x] I have added or updated tests where applicable
- [x] If this change affects the UI, I have included before/after
screenshots
- [x] I have updated relevant documentation to reflect my changes
- [x] I have considered and documented any risks above
- [x] I will address all Greptile and reviewer comments before
requesting merge

---------

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-05-19 15:52:39 -05:00
dottaandPaperclip 8fc399f511 Add guarded dev restart handling
Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-20 08:50:00 -05:00
Sai Shankar 02bf0dd862 add app version label 2026-03-17 09:40:07 +05:30
Dotta 64f5c3f837 Fix authenticated smoke bootstrap flow 2026-03-09 15:30:08 -05:00
Dotta 8ee063c4e5 feat(ui): reconcile backup UI changes with current routing and interaction features 2026-03-02 16:44:03 -06:00
ForgottenandClaude Opus 4.6 d2f9ade30c fix(ui): mobile viewport, scrollable popovers, and actor labels
- Set viewport-fit=cover and disable user scaling for mobile PWA feel
- Wrap assignee/project popover lists in scrollable containers
- Remove rounded-t-sm from stacked chart bars for cleaner rendering
- Prevent filter bar icons from shrinking on narrow screens
- Show "Board" instead of raw user IDs in activity feeds and toasts
- Surface server error message in health API failures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:44:02 -06:00
ForgottenandClaude Opus 4.6 2ec45c49af feat(ui): add auth pages, company rail, inbox redesign, and page improvements
Add Auth sign-in/sign-up page and InviteLanding page for invite acceptance.
Add CloudAccessGate that checks deployment mode and redirects to /auth when
session is required. Add CompanyRail with drag-and-drop company switching.
Add MarkdownBody prose renderer. Redesign Inbox with category filters and
inline join-request approval. Refactor AgentDetail to overview/configure/runs
views with claude-login support. Replace navigate() anti-patterns with <Link>
components in Dashboard and MetricCard. Add live-run indicators in sidebar
agents. Fix LiveUpdatesProvider cache key resolution for issue identifiers.
Add auth, health, and access API clients.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:41:21 -06:00