Commit Graph

26 Commits

Author SHA1 Message Date
xarmian 9072e49b17 feat: add CLI commands for item starring (#120)
Add star/unstar/starred CLI commands (PLAN-564, TASK-570):

- pad item star <ref> — star an item
- pad item unstar <ref> — unstar an item
- pad item starred [--all] [--format json] — list starred items

Client methods: StarItem, UnstarItem, ListStarredItems.
2026-04-14 20:51:03 -04:00
xarmian 7ca0463e70 feat: browser-based CLI authentication flow (#97)
Replace the email/password terminal prompt in `pad auth login` with a
browser-based auth flow. The CLI creates a pending session, prints a URL
the user opens in their browser (works for localhost, remote VPS, or
Pad Cloud), and polls until the session is approved.

- Add CLI auth session endpoints (create, poll, approve)
- Add browser approval page at /auth/cli/{code}
- Rewrite `pad auth login` to use browser flow by default
- Keep `pad auth login --interactive` as email/password fallback
- Add login page redirect param support for post-login bounce-back
- Add SQLite and PostgreSQL migrations for cli_auth_sessions table

Closes PLAN-539, IDEA-404
2026-04-13 10:11:16 -04:00
xarmian 5606b22007 fix: address 6 security findings from Codex review of TOTP 2FA
HIGH fixes:
- Login-verify no longer accepts bare user_id. Now requires an
  HMAC-signed, IP-bound, 5-minute challenge token issued during login
  (prevents password bypass via known user ID + TOTP code)
- Recovery codes are SHA-256 hashed before storage; plaintext is
  returned to the user once and never persisted

MEDIUM fixes:
- ConsumeRecoveryCode uses a DB transaction to prevent concurrent
  double-consumption of the same recovery code
- EnableTOTP is atomic: WHERE clause requires totp_secret match to
  prevent TOCTOU race between setup and verify calls
- /auth/2fa/login-verify now uses the strict Auth rate limiter
  (5 req/min/IP) instead of the general API limiter
- CLI login detects requires_2fa response and prompts for TOTP code
  instead of silently saving empty credentials
2026-04-08 20:30:39 +00:00
xarmian bde15d45ca Rename Phases to Plans, clean up deprecated aliases (#71)
* Rename "Phases" to "Plans" and clean up deprecated phase aliases

Renames the default "Phases" collection to "Plans" across the full stack:
- DB migration renames existing collections in-place (name, slug, prefix PLAN, icon 🗺️)
- Removes all deprecated Phase* backward-compat aliases from models and store
- Removes --phase CLI flag (use --parent instead)
- Updates convention triggers: on-phase-start/complete → on-plan-start/complete
- Updates dashboard API: active_phases → active_plans, /phases-progress → /plans-progress
- Updates all frontend components, types, and documentation

Closes IDEA-124

* Fix CSRF cookie not being cleared on logout

The SessionAuth middleware was re-issuing a CSRF cookie before the
logout handler could clear it, resulting in two Set-Cookie headers.
Skip CSRF re-issue for /api/v1/auth/ paths since auth endpoints
manage their own CSRF cookies (login sets, logout clears).

* Fix migration issues found in Codex review

- P1: Move doc_type UPDATE from migration 024 into 025, which recreates
  the table with the new CHECK constraint first (SQLite enforces CHECK
  on UPDATE, so the old constraint would reject 'plan')
- P1: Add PostgreSQL migration 005 for the collection rename (phases →
  plans) — previously only existed on the SQLite path
- P2: Recreate FTS triggers, indexes, and rebuild FTS after the table
  swap in migration 025 (DROP TABLE drops associated objects in SQLite)

* Fix parent filter field name and sync .agents skill copy

Codex review round 2 findings:
- P1: Parent filter compared against `parent_id` (wrong) instead of
  `parent_link_id` — plan filtering in collection view was broken
- P1: .agents/skills/pad/SKILL.md still had old --phase flags and
  "Phases" references — synced from the updated .claude copy
- P2: Accept legacy 'phase' filter key for backward compat with
  existing saved views that serialized the old key name

* Fix PG migration JSONB casting and add slug collision guards

Codex PR review bot findings:
- P1: PostgreSQL REPLACE/LIKE don't work on JSONB columns — cast
  schema::text and fields::text before string ops, then back to ::jsonb
- P1: If a workspace already has a custom 'plans' collection, the
  rename hits UNIQUE(workspace_id, slug) — added NOT EXISTS guard
  to both SQLite and PostgreSQL migrations
2026-04-07 14:55:23 -04:00
xarmian 063ff92d00 feat: generalized parent/child items with progress tracking (#70)
* feat: generalize parent/child items — any item can have children with progress tracking

Replaces the phases-only task widget with a generalized parent/child system.
Any item (Phase, Idea, Doc, Task, etc.) can now be a parent of child items,
getting automatic progress bars, burndown charts, status grouping, drag-drop
reordering, and recursive expand/collapse up to 3 levels deep.

DB: migrate link_type 'phase' → 'parent' (migration 023)
Store: generalized methods (GetChildItems, GetItemProgress, SetParentLink
  with cycle detection), drop collection filters, per-child terminal status
API: new /items/{slug}/children and /items/{slug}/progress endpoints
Frontend: ChildItems, ChildChart, NestedChildren components replace PhaseTasks
CLI: --parent flag (--phase kept as hidden alias), list/show/changelog updated
Docs: CLAUDE.md, SKILL.md, pad-web updated for parent/child model

Full backward compatibility: old 'phase' link_type, --phase flags, phase_id/
phase_ref JSON fields all still work as deprecated aliases.

Closes PHASE-16 (9 tasks).

* fix: update collection list page to use item_id from phasesProgress response

The TS client return type changed from phase_id to item_id but the
collection list page still referenced p.phase_id, causing svelte-check
type errors in CI.

* fix: address Codex review findings — PG migration, terminal statuses, metrics, CSRF resilience

- Add PostgreSQL migration 003 to rename 'phase' links to 'parent'
- Use schema-defined terminal statuses in GetAllItemProgress instead of hardcoded defaults
- Pass computed terminal statuses from page to ChildItems component
- Only special-case 'parent' field key when not defined in collection schema
- Move MetricsMiddleware before Recoverer so panics are counted
- Always mount ChildItems for SSE subscriptions even with 0 children
- Exclude soft-deleted children from has_children enrichment query
- Re-issue CSRF cookie when session is valid but cookie is missing
- Show actual API error messages in create-item toasts
2026-04-07 09:52:31 -04:00
xarmian 872f08aa84 feat: add compliance audit trail with IP/UA tracking
Extend the activities table to capture IP address and user agent for all
state-changing operations. Add audit events for auth (login, logout,
register, bootstrap, password changes), workspace management (member
invite/remove, role changes), token lifecycle, and admin settings.

- SQLite migration recreates activities table with nullable workspace_id,
  new ip_address/user_agent columns, and relaxed CHECK constraints
- PostgreSQL migration adds columns and drops constraints
- New ListAuditLog store method with action/actor/workspace/date filters
- GET /api/v1/audit-log endpoint (admin-only)
- CLI: pad workspace audit-log [--days N] [--actor X] [--action X]
2026-04-06 01:55:06 +00:00
xarmian be576d9e24 feat: agent roles — role-based (user, role) assignment for items (#58)
* feat: agent roles — role-based (user, role) assignment for items (#PHASE-9)

Introduce agent roles as a first-class concept for human-agent work
assignment. Roles describe capability specializations (Planner,
Implementer, Reviewer, etc.) and items can be assigned to a (user, role)
pair, enabling natural handoff workflows between different AI tools.

Migration:
- New `agent_roles` table (workspace-scoped, slug-unique)
- `assigned_user_id` + `agent_role_id` columns on `items` with FKs
- Removed legacy `assignee` text field from Tasks schema

Backend:
- AgentRole model + full CRUD store/API
- All item queries updated with LEFT JOINs to resolve assignment
- Item list filtering by assigned_user_id and agent_role_id
- Role transitions tracked in activity feed metadata

CLI:
- `pad role list/create/delete` commands
- `--role` and `--assign` flags on item create/update/list
- Assignment displayed in `pad item show` output

Web:
- TypeScript types + API client for agent roles
- Role badge on item cards in list/board views
- Assignment display on item detail page

* fix: enforce workspace-scoped assignments and fail fast on unresolved --assign filter

Addresses code review feedback from PR #58:

P1: Add validateAssignmentScope() to the store layer, called by both
CreateItem and UpdateItem. Verifies that assigned_user_id belongs to
the workspace (via IsWorkspaceMember) and agent_role_id exists in the
workspace (via GetAgentRole) before writing. Prevents cross-workspace
assignment leaks.

P2: The CLI `pad item list --assign <name>` now errors instead of
silently returning unfiltered results when the member lookup fails or
no workspace member matches the provided name.
2026-04-03 21:16:38 -04:00
xarmian 89db556e29 feat(server): add info command for TASK-134 (#52) 2026-04-02 21:44:08 -04:00
xarmian 35f3dd1da4 feat(conventions): add structured metadata for TASK-133 (#51)
* feat(conventions): add structured metadata for TASK-133

* fix(web): add workspace update type for CI
2026-04-02 18:39:51 -04:00
xarmian 9650c0ec0b feat(workspaces): populate context during onboarding for TASK-132 (#50)
* feat(web): add workspace context editor for TASK-131

* feat(workspaces): populate context during onboarding for TASK-132
2026-04-02 16:24:21 -04:00
xarmian f5649b912e refactor(cli): group first-release commands for TASK-127 (#45) 2026-04-02 15:28:16 -04:00
xarmian b59f50982f feat(auth): add local bootstrap setup for TASK-118 (#37)
* feat(auth): add local bootstrap setup for TASK-118

* fix(auth): honor setup-required bootstrap flow
2026-04-02 05:13:17 -04:00
xarmian a2a25b176a refactor(auth): make setup state explicit for TASK-117 (#36) 2026-04-01 22:21:26 -04:00
xarmian 5db077a2a3 refactor(cli): limit local server autostart to local mode for TASK-116 (#35) 2026-04-01 21:56:18 -04:00
xarmian 123a7aec98 feat(cli): add client configure flow for TASK-115 (#34) 2026-04-01 21:32:55 -04:00
xarmian 07ff6faed7 feat: global skill installation registry and detection fixes (#25)
Track all skill installations in ~/.pad/installations.json so
`pad install --update` can update stale skill files across every
project in one shot. Also fixes false Copilot detection on projects
that have .github/ for CI but don't use Copilot.

- Add Installation registry (internal/cli/registry.go) with
  record, prune, status, and update-all operations
- Record installations from all install code paths (install,
  init, skills install, interactive, --all, --update)
- `pad install --list` / `pad skills status` now show tracked
  installations across all projects with freshness indicators
- `pad install --update` / `pad skills update` now update stale
  files globally, not just the current directory
- `pad skills update` and `pad skills status` delegate to the
  same logic as `pad install --update` and `pad install --list`
- Fix Copilot detection: use .github/copilot or .github/instructions
  instead of .github (which exists on most projects for CI)
- Add .codex to agents detection directories
- `pad init` on already-linked workspaces now records existing
  installations in the registry
2026-03-30 11:31:05 -04:00
xarmian a219f81633 fix: CLI and skill file now use issue IDs (TASK-5) instead of slugs (#15)
Agents were using verbose slugs because:
1. The skill file (SKILL.md) taught them to use `<slug>` in every example
2. CLI output showed slugs in parentheses rather than issue IDs
3. CLI usage strings said `<slug>` not `<ref>`
4. JSON output lacked a `ref` field, so agents parsing JSON only saw slugs

Changes:
- Add computed `ref` field to Item model (e.g. "TASK-5") in JSON output
- CLI create/update/delete/edit output now prominently shows issue IDs
- All CLI usage strings changed from `<slug>` to `<ref>`
- Issue IDs displayed in bold cyan (not dim) in list/show/grouped views
- Skill file rewritten to use issue IDs in all examples and instructions
- Dashboard API includes `item_ref`/`ref` in attention, suggestions, phases
- Search results now include item_number and collection_prefix for refs
- CLAUDE.md updated to document issue ID usage
2026-03-28 16:14:32 -04:00
xarmian 46447e5504 feat: user management & authentication (Phase 6) (#14)
* feat: add user management database migration and models

Add migration 012_users.sql with users, sessions, and workspace_members
tables. Add user_id columns to api_tokens, items, comments, activities,
item_links, and item_versions for proper user attribution. Create Go
model structs (User, Session, WorkspaceMember) in models/user.go.

* feat: add store layer for users, sessions, and workspace members

Implement CRUD operations for user management:
- users.go: create, get, update, list, validate password (bcrypt)
- sessions.go: create, validate, delete, cleanup expired (SHA-256 hashed tokens)
- workspace_members.go: add/remove members, role management, access checks

Adds golang.org/x/crypto/bcrypt dependency. Includes 16 new tests
covering all store methods, password validation, session lifecycle,
and workspace membership operations.

* feat: rewrite auth system from single-password to user-based

Replace single-password auth with email/password user authentication:
- New endpoints: POST /auth/register, GET /auth/me
- Rewritten: POST /auth/login (email+password), GET /auth/session
  (needs_setup detection), POST /auth/logout (DB session destroy)
- Delete in-memory SessionManager, use DB-backed sessions via store
- New middleware: SessionAuth (cookie→user), RequireAuth (with
  fresh-install passthrough when no users exist)
- Remove Password field from config, PAD_PASSWORD env var, SetPassword()

All 23 existing server tests pass (fresh DBs have no users → passthrough).

* feat: add workspace access control middleware

Add RequireWorkspaceAccess middleware that checks workspace_members for
authenticated users, with fallback for legacy API tokens and fresh
installs (no users → implicit owner). Includes role hierarchy helpers
(workspaceRole, requireRole) for downstream permission checks.
Wire middleware into the /{slug} workspace route group.

* feat: add CLI auth commands and credential storage

Add pad login, pad logout, pad whoami commands with credential
storage in ~/.pad/credentials.json (0600 permissions). Update CLI
HTTP client to auto-attach auth tokens and X-Pad-Agent header on
all requests. Add auth API methods (Login, Register, Logout,
CheckSession, GetCurrentUser). Extend .pad.toml with optional
agent_name field. Add golang.org/x/term for masked password input.

* feat: derive actor/source from auth context in all handlers

Replace hardcoded "user"/"web" actor/source strings with auth-aware
helpers. actorFromRequest() derives actor ("user"/"agent" via
X-Pad-Agent header) and source ("web"/"cli" from auth method).
agentMeta() merges agent name into activity metadata. Update all
item, document, comment, and move handlers to use request-based
logActivity/logActivityWithMeta. Remove hardcoded CreatedBy/Source
from all CLI commands — server now determines these from auth context.

* feat: frontend auth — login, registration, auth guard, user menu

Rewrite login page with email/password fields, add registration page
for first-time setup, update auth guard to handle needs_setup redirect.
Add user menu to sidebar with logout. Update API client with new auth
methods (register, login with email, session with needs_setup flag).

* feat: migrate API tokens from workspace-scoped to user-owned

API tokens now have a user_id owner and optional workspace_id scope.
CreateAPIToken takes userID as first parameter. ValidateToken resolves
the token's user into the request context. TokenAuth middleware now
sets ctxCurrentUser when a user-owned API token is used. Add user-
scoped endpoints: GET/POST/DELETE /auth/tokens. Keep workspace-scoped
token endpoints for backwards compatibility.

* feat: workspace membership, invitations, and role enforcement

Add workspace_invitations table (migration 013) with join codes.
Implement invitation store methods (create, get by code, accept,
list). Add member management handlers: list members + invitations,
invite (auto-adds existing users or creates invitation), remove
member, change role, accept invitation by code. Add API routes
under /workspaces/{slug}/members/* and /invitations/{code}/accept.
Add CLI commands: pad members, pad invite, pad join.

* feat: auth tests and documentation updates

Add comprehensive auth endpoint tests: registration flow (first user
becomes admin), login/logout, validation errors, duplicate email,
auth enforcement (401 after users exist, exempt paths), /me endpoint.
Update CLAUDE.md and README.md to document user-based auth system,
replacing old PAD_PASSWORD references with pad login/members/invite
workflow and role-based access control.

* feat: add members management UI to workspace settings page

Add Members section to settings with: member list (avatar, name,
email, role), role change dropdown (owner only), remove button
(owner only), pending invitations display with join codes, and
invite form with email + role picker. Add members API methods to
the TypeScript client (list, invite, remove, updateRole).

* fix: backfill workspace owners for pre-migration workspaces

Add backfillWorkspaceOwners() that runs on server start. For any
workspace with no members, adds the first admin user as owner.
This handles the migration case where workspaces existed before the
user system — without it, the members list shows empty.

* feat: shareable invite links with /join/[code] page

Replace raw join codes with full shareable URLs. Server generates
join_url using its configured base URL (e.g. https://pad.example.com/
join/a3f8b2c1). New /join/[code] page handles the full flow: checks
auth → shows login/register if needed → accepts invitation → redirects
to workspace. Settings page shows "Copy invite link" button that copies
URL to clipboard. CLI outputs shareable link instead of raw code.

* fix: auto-add workspace creator as owner, integrate auth into pad init

handleCreateWorkspace now adds the authenticated user as owner of the
new workspace immediately — no more relying on the startup backfill.

pad init now checks auth status before making API calls. If no users
exist, prompts to register. If not logged in, prompts to login. After
auth, proceeds with workspace creation normally.

* fix: add join_url to invite response type in API client

* fix: address codex review — invite registration, logout token revocation, workspace scoping

- Allow registration with valid invitation_code (fixes invite flow for new users)
- Revoke Bearer session tokens on logout, not just cookies
- Filter workspace listing to user's memberships (admins see all)
2026-03-28 15:43:09 -04:00
xarmian dc83d7490c feat: Add content templates for collections
Collections can now define a content_template in their settings — a
markdown template that pre-fills new items. When creating a bug report,
for example, the template can include "Steps to Reproduce", "Expected
Behavior", "Actual Behavior" sections automatically.

- Add content_template to CollectionSettings (Go model + TypeScript type)
- Sidebar "New" button uses template when creating items
- Dashboard quick-create buttons use template
- Template is stored in collection settings JSON, configurable via
  the collection edit UI
2026-03-28 14:07:07 +00:00
xarmian 823afe615c feat: Add terminal colors and improved CLI formatting
Add fatih/color dependency for terminal color output. Status colors
(green=done, yellow=in-progress, blue=open, red=cancelled),
priority colors, item reference numbers in all list output, and
colorized status icons throughout the CLI.
2026-03-28 13:54:41 +00:00
xarmian 6daa8eb68b Add move item between collections with field migration
Full-stack feature: move items between collections (e.g., idea → task)
with automatic field migration.

Backend:
- Field migration engine (items/migrate.go) maps matching fields,
  handles type conversions, drops incompatible fields, applies defaults
- Store method updates collection_id and assigns new item_number
- POST /api/v1/workspaces/{ws}/items/{slug}/move endpoint
- Activity logging with "moved" action and from/to metadata
- 6 migration unit tests covering type matching, conversion, and edge cases

CLI:
- pad move <slug> <target-collection> [--field key=value ...]
- Accepts singular collection names (task, idea, bug, etc.)

Web UI:
- "Move to..." dropdown on item detail page
- Shows all collections except current with icons
- Redirects to the item's new URL after move

Field migration rules:
- Same type: transfer directly (validate select options)
- Compatible types (text↔url, number→text, select→text): auto-convert
- Incompatible types: drop silently
- Missing required target fields: apply defaults or error
2026-03-28 05:01:40 +00:00
xarmian b18ca1f3fc Add multi-agent pad install command
New top-level `pad install` command that auto-detects AI coding tools and
installs the /pad skill with tool-appropriate frontmatter:
- Claude Code (.claude/skills/) — full frontmatter
- Codex/Cursor/Windsurf (.agents/skills/) — name+description only
- GitHub Copilot (.github/instructions/) — applyTo frontmatter
- Amazon Q (.amazonq/rules/) — no frontmatter
- JetBrains Junie (.junie/guidelines/) — no frontmatter

Supports: pad install, pad install <tool>, pad install --all, --list, --update.
Updates pad init to detect and offer multi-tool installation.
2026-03-28 03:58:52 +00:00
xarmian dbecb741c6 Add workspace export/import and fix create workspace modal
Export/Import:
- `pad export -o file.json` exports workspace (collections, items,
  comments, links, versions) to portable JSON
- `pad import file.json --name X` creates new workspace with
  regenerated UUIDs and remapped relations
- GET /workspaces/{slug}/export and POST /workspaces/import endpoints
- "Download JSON" button in workspace settings
- Import tab with drag-and-drop in the create workspace modal
- Full transaction wrapping for atomic imports

Create Workspace Modal:
- Extracted from sidebar dropdown into a proper centered modal
  (sidebar's CSS transform was trapping fixed-position elements)
- Rendered at root layout level via uiStore flag
- Create and Import tabs with template picker and file drop zone
2026-03-28 00:25:04 +00:00
xarmian d318ecf7fc Add workspace onboarding: CLI hints, web checklist, codebase detection, and relation field fix
- Print suggested /pad prompts after `pad init` creates a new workspace
- Add `pad onboard` command that detects project tooling (language, build system,
  test runner, CI, linter) and suggests matching conventions from the library
- Replace empty workspace welcome box with OnboardingChecklist component showing
  a 4-step guided setup with progress bar and /pad prompt hints
- Add contextual tips with /pad prompts to empty collection states
- Add onboarding workflow to /pad skill for agent-driven codebase analysis
- Fix relation fields storing slugs instead of UUIDs: server now resolves
  slugs/refs to UUIDs for relation-type fields on both create and update
2026-03-27 19:33:18 +00:00
xarmian 7ba69abb88 Misc improvements: CLI field summaries, editor enhancements, CI and UI polish
Show field summary after create/update CLI commands. Make svelte-check
blocking in CI. Improve editor block handling, field editor layout,
conventions page, and minor UI consistency fixes across pages.
2026-03-27 01:13:07 +00:00
xarmian 81579847c6 Initial release
Pad — project management for developers and AI agents.
Single Go binary with embedded SvelteKit web UI, SQLite storage,
CLI, and Claude Code /pad skill integration.

https://getpad.dev
2026-03-26 01:52:36 +00:00