Commit Graph

9 Commits

Author SHA1 Message Date
Jannes Stubbemann 8ddd735a7a feat(ui): theme toggle on unauthenticated auth page (supersedes part of #3732) (#5874)
## Thinking Path

> - Paperclip orchestrates AI agents for zero-human companies
> - Operators sign in via the `/auth` page, which renders before any
session exists
> - The signed-in app has a theme toggle inside `SidebarAccountMenu`,
but the signed-out `/auth` page has none — first-time visitors are stuck
in whichever theme was hardcoded at boot
> - Master's existing toggle was inline inside `SidebarAccountMenu.tsx`
as a `MenuAction` row, not exported as a reusable widget; round-1 of
this PR added a standalone `ThemeToggle` but punted on unifying the two
surfaces
> - This pull request makes `ThemeToggle` the canonical theme widget
(one source of truth for label, icon, and toggle behaviour), used both
as a compact icon button on `/auth` and as a full-width menu row in
`SidebarAccountMenu`
> - The benefit is a working pre-auth theme switch and zero risk of the
two call sites drifting out of sync as the theme model evolves

## Linked Issues or Issue Description

No existing issue covers this directly — problem described in-PR
(feature-gap shape):

- The signed-in app has a theme toggle inside `SidebarAccountMenu`, but
the signed-out `/auth` page has none — first-time visitors are stuck in
whichever theme was hardcoded at boot.
- The existing toggle lived inline in `SidebarAccountMenu.tsx` as a
`MenuAction` row, not exported as a reusable widget, so the two surfaces
could drift apart as the theme model evolves.
- This PR supersedes part of PR #3732 (the auth-page toggle slice); no
standalone issue was filed for it.

Duplicate-PR search: related open theme PRs #2769 and #4666 add in-app
three-state system-theme toggles — different surface from this PR
(unauthenticated auth page); sibling PR in this series: #5873.

## What Changed

- **`ui/src/components/ThemeToggle.tsx`** — accepts `variant: "icon" |
"menu-action"` (default `"icon"`) and an `onAfterToggle` callback. Both
variants share `useTheme` and the same label/icon derivation. The
`menu-action` variant matches the existing `MenuAction` row styling.
- **`ui/src/components/SidebarAccountMenu.tsx`** — drops its inline
`useTheme()` + `MenuAction`-for-the-theme-row in favor of `<ThemeToggle
variant="menu-action" onAfterToggle={() => setOpen(false)} />`. Sun/Moon
icon imports and theme state move with it.
- **`ui/src/pages/Auth.tsx`** — unchanged from round 0; renders
`<ThemeToggle />` at top-right of the `/auth` page (already using the
default `icon` variant).
- **`ui/src/components/ThemeToggle.test.tsx`** (new) — covers both
variants, the `onAfterToggle` callback, and the label/icon flip across
themes.
- **`ui/src/components/SidebarAccountMenu.test.tsx`** — unchanged; its
`ThemeContext` mock still works because `ThemeToggle` uses the same
hook.

## Verification

- `pnpm --filter @paperclipai/ui run typecheck` — clean.
- `npx vitest run src/components/ThemeToggle.test.tsx
src/components/SidebarAccountMenu.test.tsx` — 5 passed (4 new + 1
existing).
- Manual: launched `pnpm dev` for the UI, mocked `/api/auth/get-session`
401, navigated to `/auth` — toggle is visible top-right, click flips
light/dark. Screenshots committed.

## Risks

Low. The change is structural — both call sites render the same widget
that already worked on each surface independently.
`SidebarAccountMenu`'s popover behaviour is preserved via
`onAfterToggle`, and `ThemeContext` is untouched.

## Model Used

Claude Opus 4.7 (1M context), extended thinking mode.

## Checklist

- [x] I have searched GitHub for duplicate or related PRs and linked
them above
- [x] Thinking path traces from project context to this change
- [x] Model used specified
- [x] Checked ROADMAP.md — not in conflict with planned core work
- [x] Tests run locally and pass
- [x] Added tests for the new ThemeToggle component (both variants)
- [x] UI change — before/after screenshots in
`docs/pr-screenshots/pr-5874/`
- [x] No documentation updates required (purely internal refactor + new
component)
- [x] Documented risks above
- [x] Will address all Greptile and reviewer comments before merge

Supersedes part of #3732.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Devin Foley <devin@paperclip.ing>
2026-06-12 12:59:14 -07:00
Dotta 139cdebe51 [codex] Improve login accessibility and password-manager metadata (#7660)
## Thinking Path

> - Paperclip is the open source app people use to manage AI agents for
work.
> - Human operators sign in through the main auth page and through
invite acceptance flows.
> - Those forms need to be understandable to assistive technology and
password managers.
> - The login fields did not consistently expose stable names, ids,
autocomplete hints, required state, and error relationships.
> - That made it easier for password managers such as 1Password to miss
the username/password pairing and harder for screen readers to associate
validation errors.
> - This pull request tightens the auth and invite form metadata while
keeping the visible flow unchanged.
> - The benefit is a smoother login and invite-acceptance experience
without changing server-side auth behavior.

## Linked Issues or Issue Description

No matching GitHub issue found after searching `login accessibility
1Password username password` in `paperclipai/paperclip` issues and PRs.

## What happened?

Login and invite auth fields were missing password-manager and
accessibility metadata, including stable field identifiers, autocomplete
hints, required semantics, and error-region relationships. That made it
easier for password managers such as 1Password to miss the
username/password pairing and harder for screen readers to associate
validation errors.

## Expected behavior

Auth fields should be discoverable as username/password fields,
distinguish sign-in and sign-up password autocomplete behavior, and
expose validation errors through an alert region referenced by invalid
inputs.

## Steps to reproduce

1. Open the main `/auth` form or an invite auth form.
2. Inspect the email, password, and sign-up name field attributes.
3. Trigger a validation/auth error and inspect whether invalid inputs
reference the displayed error text.

## Paperclip version or commit

Prior to this PR on `master`.

## Deployment mode

Board UI, all deployments using these forms.

## What Changed

- Added stable `id`, `name`, `required`, `aria-required`,
`aria-invalid`, `aria-describedby`, and autocomplete metadata to the
main auth form.
- Added invite auth field metadata so invite sign-up uses
`new-password`, invite sign-in uses `current-password`, and the email
field is recognized as `username`.
- Added alert regions for auth and invite auth errors so invalid fields
can reference the displayed error text.
- Added focused Vitest coverage for the main auth form and invite auth
flow metadata/error behavior.

## Verification

- `pnpm exec vitest run ui/src/pages/Auth.test.tsx
ui/src/pages/InviteLanding.test.tsx` passes: 2 files, 16 tests.
- `pnpm build` passes locally.
- PR CI is green on head `3531d1900`, including Build, Canary Dry Run,
Typecheck + Release Registry, e2e, general/serialized test shards,
policy, commitperclip review, security checks, and aggregate `verify`.
- Greptile Review is passing on head `3531d1900`; the P2
alert/live-region review thread was fixed and resolved.
- Rebasing onto `public-gh/master` completed cleanly; current base ref
is `e50666e4c`.
- Confirmed the branch diff does not include `pnpm-lock.yaml`,
`.github/workflows`, migrations, or design/image assets.
- No screenshots attached: this is a form metadata/accessibility change,
and the task specifically asked not to add design screenshots or images
unless they are part of the work.

## Risks

Low risk. The change is limited to UI form attributes and error wiring.
Main risk is password-manager/browser interpretation differences,
covered by asserting the emitted DOM metadata rather than a specific
vendor integration.

> 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 model with repository tool use and
shell execution. Exact hosted model ID/context window are not exposed in
this 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 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 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] 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: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-06 11:40:59 -05:00
Dotta b9a80dcf22 feat: implement multi-user access and invite flows (#3784)
## Thinking Path

> - Paperclip is the control plane for autonomous AI companies.
> - V1 needs to stay local-first while also supporting shared,
authenticated deployments.
> - Human operators need real identities, company membership, invite
flows, profile surfaces, and company-scoped access controls.
> - Agents and operators also need the existing issue, inbox, workspace,
approval, and plugin flows to keep working under those authenticated
boundaries.
> - This branch accumulated the multi-user implementation, follow-up QA
fixes, workspace/runtime refinements, invite UX improvements,
release-branch conflict resolution, and review hardening.
> - This pull request consolidates that branch onto the current `master`
branch as a single reviewable PR.
> - The benefit is a complete multi-user implementation path with tests
and docs carried forward without dropping existing branch work.

## What Changed

- Added authenticated human-user access surfaces: auth/session routes,
company user directory, profile settings, company access/member
management, join requests, and invite management.
- Added invite creation, invite landing, onboarding, logo/branding,
invite grants, deduped join requests, and authenticated multi-user E2E
coverage.
- Tightened company-scoped and instance-admin authorization across
board, plugin, adapter, access, issue, and workspace routes.
- Added profile-image URL validation hardening, avatar preservation on
name-only profile updates, and join-request uniqueness migration cleanup
for pending human requests.
- Added an atomic member role/status/grants update path so Company
Access saves no longer leave partially updated permissions.
- Improved issue chat, inbox, assignee identity rendering,
sidebar/account/company navigation, workspace routing, and execution
workspace reuse behavior for multi-user operation.
- Added and updated server/UI tests covering auth, invites, membership,
issue workspace inheritance, plugin authz, inbox/chat behavior, and
multi-user flows.
- Merged current `public-gh/master` into this branch, resolved all
conflicts, and verified no `pnpm-lock.yaml` change is included in this
PR diff.

## Verification

- `pnpm exec vitest run server/src/__tests__/issues-service.test.ts
ui/src/components/IssueChatThread.test.tsx ui/src/pages/Inbox.test.tsx`
- `pnpm run preflight:workspace-links && pnpm exec vitest run
server/src/__tests__/plugin-routes-authz.test.ts`
- `pnpm exec vitest run server/src/__tests__/plugin-routes-authz.test.ts
server/src/__tests__/workspace-runtime-service-authz.test.ts
server/src/__tests__/access-validators.test.ts`
- `pnpm exec vitest run
server/src/__tests__/authz-company-access.test.ts
server/src/__tests__/routines-routes.test.ts
server/src/__tests__/sidebar-preferences-routes.test.ts
server/src/__tests__/approval-routes-idempotency.test.ts
server/src/__tests__/openclaw-invite-prompt-route.test.ts
server/src/__tests__/agent-cross-tenant-authz-routes.test.ts
server/src/__tests__/routines-e2e.test.ts`
- `pnpm exec vitest run server/src/__tests__/auth-routes.test.ts
ui/src/pages/CompanyAccess.test.tsx`
- `pnpm --filter @paperclipai/shared typecheck && pnpm --filter
@paperclipai/db typecheck && pnpm --filter @paperclipai/server
typecheck`
- `pnpm --filter @paperclipai/shared typecheck && pnpm --filter
@paperclipai/server typecheck`
- `pnpm --filter @paperclipai/ui typecheck`
- `pnpm db:generate`
- `npx playwright test --config tests/e2e/playwright.config.ts --list`
- Confirmed branch has no uncommitted changes and is `0` commits behind
`public-gh/master` before PR creation.
- Confirmed no `pnpm-lock.yaml` change is staged or present in the PR
diff.

## Risks

- High review surface area: this PR contains the accumulated multi-user
branch plus follow-up fixes, so reviewers should focus especially on
company-boundary enforcement and authenticated-vs-local deployment
behavior.
- UI behavior changed across invites, inbox, issue chat, access
settings, and sidebar navigation; no browser screenshots are included in
this branch-consolidation PR.
- Plugin install, upgrade, and lifecycle/config mutations now require
instance-admin access, which is intentional but may change expectations
for non-admin board users.
- A join-request dedupe migration rejects duplicate pending human
requests before creating unique indexes; deployments with unusual
historical duplicates should review the migration behavior.
- Company member role/status/grant saves now use a new combined
endpoint; older separate endpoints remain for compatibility.
- Full production build was not run locally in this heartbeat; CI should
cover the full matrix.

## Model Used

- OpenAI Codex coding agent, GPT-5-based model, CLI/tool-use
environment. Exact deployed model identifier and context window were not
exposed by the 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 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

Note on screenshots: this is a branch-consolidation PR for an
already-developed multi-user branch, and no browser screenshots were
captured during this heartbeat.

---------

Co-authored-by: dotta <dotta@example.com>
Co-authored-by: Paperclip <noreply@paperclip.ing>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 09:44:19 -05:00
Dotta 7576c5ecbc Update ui/src/pages/Auth.tsx
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
2026-03-23 19:00:34 -05:00
dotta cd7c6ee751 Fix login form not being detected by 1Password
Add name, id, and htmlFor attributes to form inputs and a method/action
to the form element so password managers can properly identify the login
form fields.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 16:57:27 -05:00
Devin Foley 88df0fecb0 fix: show validation error on incomplete login submit
Address Greptile review feedback:
- Show "Please fill in all required fields." instead of silently
  returning when form is submitted with missing fields
- Remove pointer-events-none so keyboard users can reach the
  button and receive the same validation feedback

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-15 19:39:12 -07:00
Devin Foley 8a201022c0 Fix Enter key not submitting login form
The submit button's `disabled` attribute prevented browsers from firing
implicit form submission (Enter key) per HTML spec. Move the canSubmit
guard into the onSubmit handler and use aria-disabled + visual styles
instead, so Enter works when fields are filled.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-03-14 00:17:39 -07:00
Dotta 8ee063c4e5 feat(ui): reconcile backup UI changes with current routing and interaction features 2026-03-02 16:44:03 -06:00
Forgotten 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