Expand structured logging across client and API usage flows#5
Merged
2witstudios merged 1 commit intomasterfrom Sep 24, 2025
Merged
Conversation
2witstudios
added a commit
that referenced
this pull request
Dec 22, 2025
- Wrap switch case declarations in blocks to prevent variable leakage - Add isActivityEligibleForRollback() helper for DRY rollback checks - Export helper for use in history API routes Addresses PR #118 review issues #5, #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2witstudios
added a commit
that referenced
this pull request
Dec 23, 2025
Fixes Issues #5 and #7 from PR #118 review: Context determination (#5): - Align executeAiUndo context logic with previewAiUndo - Use 'ai_tool' context for pages (all activities here are AI-generated) - Simplifies from switch statement to direct assignment with drive check Transaction atomicity (#7): - Wrap rollbacks AND message deletion in single transaction - Pass transaction to executeRollback for atomic operations - If any operation fails, entire undo is rolled back This ensures users don't end up in inconsistent states where messages are deleted but only some changes were reverted. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2witstudios
added a commit
that referenced
this pull request
Dec 23, 2025
* feat: add version history and rollback functionality Implement comprehensive version history browsing and rollback capabilities for PageSpace, allowing users to restore resources to previous states. ## Schema Changes - Add 'rollback' operation to activity_operation enum - Add rollbackFromActivityId and contentFormat fields to activity_logs - Create retention_policies table for plan-based history retention ## Core Features - RBAC-based rollback permissions (edit access = rollback access) - Resource-specific rollback handlers (pages, drives, agents, etc.) - Plan-based retention limits (7/30/90/unlimited days) - Rollback creates new activity entry (history never erased) ## API Endpoints - GET /api/activities/[activityId] - Single activity with rollback eligibility - POST /api/activities/[activityId]/rollback - Execute rollback - GET /api/pages/[pageId]/history - Page version history - GET /api/drives/[driveId]/history - Drive version history (admin) ## UI Components - VersionHistoryPanel - Slide-out panel with timeline and filters - VersionHistoryItem - Activity item with "Restore" action - RollbackConfirmDialog - Confirmation modal with warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: complete rollback handler implementations and fix lint errors - Fully implement rollbackPermissionChange for grant/revoke/update operations - Fully implement rollbackMemberChange for add/remove/role change operations - Fully implement rollbackRoleChange for create/delete/update operations - Fix lint errors: remove unused imports, fix useEffect dependencies - Add package exports for @pagespace/lib/permissions and @pagespace/lib/monitoring - Fix useToast import path to use correct hook location 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add undo AI changes feature for conversations Add ability to undo AI changes from a specific message point: - Preview what will be affected before undoing - Two modes: revert conversation only OR revert with all tool changes - Activity logging for audit compliance New files: - ai-undo-service.ts: preview and execute functions - UndoAiChangesDialog.tsx: confirmation dialog with mode selection - /api/ai/chat/messages/[messageId]/undo: GET preview, POST execute Changes: - Add conversation_undo operations to activity schema - Add message rollback handler to rollback-service - Wire undo button to MessageActionButtons and MessageRenderer 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add missing radio-group UI component Required for UndoAiChangesDialog mode selection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add @radix-ui/react-radio-group dependency Required for radio-group UI component used in UndoAiChangesDialog. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: restore correct @electron/node-gyp resolution in lockfile The previous lockfile had a malformed git SSH URL that broke CI: - Before: git+https://git@github.com:electron/node-gyp.git (broken) - After: https://codeload.github.com/electron/node-gyp/tar.gz/... (works) Restored lockfile and re-ran pnpm install to properly resolve dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add critical rules to CLAUDE.md and fix retention tier order - Add CRITICAL rules for package manager (always pnpm, never npm) - Add CRITICAL rules for database migrations (never manually edit) - Fix retention days: founder=90, business=unlimited (was swapped) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add missing default and rollback index - Add DEFAULT now() for retention_policies.updatedAt column - Add index on activity_logs.rollbackFromActivityId for queries - Create migration 0027_fix_retention_updated_at.sql Addresses PR #118 review issues #10, #20 * fix(lib/permissions): add block scoping and eligibility helper - Wrap switch case declarations in blocks to prevent variable leakage - Add isActivityEligibleForRollback() helper for DRY rollback checks - Export helper for use in history API routes Addresses PR #118 review issues #5, #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lib/monitoring): add rollback fields to ActivityLogInput - Add contentFormat field for content type tracking - Add rollbackFromActivityId for rollback chain references - Pass fields as top-level properties to logActivity Addresses PR #118 review issue #3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): add authorization and resourceType filtering - Add permission check before returning activity details - Implement resourceType query parameter filtering in history routes - Use shared isActivityEligibleForRollback helper - Add case-insensitive resource type matching Addresses PR #118 review issues #6, #7, #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): improve type safety and add transactions - Use Drizzle count() instead of .length for efficient queries - Add operation validation against known valid operations - Fix unsafe null type assertion in RollbackPreview - Re-export RollbackContext type for API route usage - Wrap AI undo mutations in database transaction - Use switch statement for context determination Addresses PR #118 review issues #2, #16, #18, #19, #23 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): add CSRF protection and improve error handling - Use post() with CSRF token for rollback requests - Add error toast for failed preview fetch - Handle non-JSON error responses gracefully - Fix non-existent postWithAuth import to use post - Remove re-throw after toast notification - Fix redundant ternary for buttonSize Addresses PR #118 review issues #1, #8, #11, #17, #22, NEW 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): address schema issues from PR #118 review Critical & Major fixes: - Add missing .defaultNow() to retention_policies.updatedAt (fixes schema/migration mismatch that would cause insert failures) - Add contentFormatEnum for type-safe content format validation (prevents invalid values during rollback parsing) - Add CHECK constraint: retentionDays >= -1 (where -1 = unlimited) - Add rollback source snapshot fields for audit trail preservation: - rollbackSourceOperation: captures source activity type - rollbackSourceTimestamp: captures when source change occurred - rollbackSourceTitle: captures resource title at time of change These denormalized fields survive retention policy deletion, ensuring complete audit trails even when source activities are purged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lib): move rollback fields to top-level in activity logger Fixes Major issue #2 from PR #118 review: - Move rollbackFromActivityId from metadata to top-level field - Move contentFormat from metadata to top-level field - Add rollback source snapshot fields to ActivityLogInput interface - Update logRollbackActivity to accept and pass snapshot fields Fields are now stored in dedicated database columns instead of being nested in the metadata JSONB, enabling proper indexing and querying. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): add transaction support to rollback service Enables atomic rollback operations (Issue #7 from PR #118 review): - Add optional transaction parameter to executeRollback() - Update all internal rollback functions to accept database parameter - Pass rollback source snapshot fields to logRollbackActivity When a transaction is provided, all database operations use it instead of the default db connection, enabling atomic rollback + message deletion in AI undo operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): improve atomicity and context logic in AI undo Fixes Issues #5 and #7 from PR #118 review: Context determination (#5): - Align executeAiUndo context logic with previewAiUndo - Use 'ai_tool' context for pages (all activities here are AI-generated) - Simplifies from switch statement to direct assignment with drive check Transaction atomicity (#7): - Wrap rollbacks AND message deletion in single transaction - Pass transaction to executeRollback for atomic operations - If any operation fails, entire undo is rolled back This ensures users don't end up in inconsistent states where messages are deleted but only some changes were reverted. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): use Zod schema for undo route validation Fixes Issue #6 from PR #118 review: - Replace manual mode validation with Zod schema - Aligns with codebase patterns (see rollback route, history route) - Provides type-safe body parsing with proper TypeScript inference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address CodeRabbit review feedback - Add CHECK constraint to retentionPolicies schema definition (aligns Drizzle schema with existing migration constraint) - Change AI undo to all-or-nothing transaction semantics (any rollback failure aborts entire operation) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add subscriptionTier enum for retention policies - Create subscription_tier pgEnum with 'free', 'pro', 'business', 'founder' - Convert retentionPolicies.subscriptionTier from text to enum - Adds DB-level validation to prevent invalid tier values 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address final CodeRabbit review comments - Add comments explaining rollbackFromActivityId intentionally lacks FK (allows provenance to survive source activity deletion for audit) - Add TODO note for contentSnapshot storage considerations - Optimize message fetching: include createdAt in AiUndoPreview to avoid double database query 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add USING clause for text-to-enum cast PostgreSQL requires explicit cast when converting text column to enum type. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ai): support undo for global assistant messages by checking both messages tables and updating permission logic * fix(ai): resolve lint errors in undo route and tests * test: add contract tests for version history rollback - Add route tests for /api/activities/[activityId]/rollback (12 tests) - Add route tests for /api/pages/[pageId]/history (21 tests) - Add service tests for ai-undo-service (16 tests) with @scaffold label - Add service tests for rollback-service (28 tests) with @scaffold label - Add permission tests for rollback-permissions (69 tests) - Fix undo route test: remove duplicate test expecting wrong status - Add fake timers to history route tests for deterministic dates Per rubric v2: service tests use @scaffold labels for ORM chain mocks pending repository seam refactoring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): add rollback capability to activity views Add "Restore this version" action to activity items in: - ActivityDashboard (middle panel for /dashboard/activity and drive activity) - SidebarActivityTab (right sidebar context-aware activity feed) Changes: - ActivityItem: Add hover dropdown menu with rollback action and confirmation dialog - ActivityTimeline: Pass context and onRollback handler to items - ActivityDashboard: Handle rollback with proper context mapping (user→user_dashboard, drive→drive) - SidebarActivityTab: Add rollback UI with context-aware scoping (page/drive/user_dashboard) Rollback is properly scoped by context to prevent unintended changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add activity logger tests for rollback and undo operations Add compliance tests for: - logRollbackActivity: validates rollback operation logging with source activity reference - logConversationUndo: validates conversation undo logging for both modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(rollback): support create operation rollback and global messages - Add 'create' as rollbackable operation (trash resource to undo creation) - Support both global messages and page chat messages in rollback - Fix AI undo timing to include tool calls from preceding message - Handle message create rollback by deactivating the message 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address PR #118 code review feedback - Fix build failure: replace dynamic db.query[] bracket notation with explicit conditional to resolve TypeScript union type error - Extract checkUndoPermissions() helper to eliminate 31 lines of duplicated permission logic between GET and POST handlers - Add existingPreview parameter to executeAiUndo() to avoid redundant preview computation (was being called twice per request) - Simplify context determination: remove redundant isAiGenerated check since query already filters for it - Update tests to match new 4-parameter executeAiUndo signature - Add clarifying comment explaining partial failure tests document defensive handling (actual impl uses all-or-nothing transaction) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: resolve header loading and rendering issues across all page types * style: add truncation for page titles and breadcrumb items --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2witstudios
added a commit
that referenced
this pull request
Dec 23, 2025
* feat: add version history and rollback functionality Implement comprehensive version history browsing and rollback capabilities for PageSpace, allowing users to restore resources to previous states. ## Schema Changes - Add 'rollback' operation to activity_operation enum - Add rollbackFromActivityId and contentFormat fields to activity_logs - Create retention_policies table for plan-based history retention ## Core Features - RBAC-based rollback permissions (edit access = rollback access) - Resource-specific rollback handlers (pages, drives, agents, etc.) - Plan-based retention limits (7/30/90/unlimited days) - Rollback creates new activity entry (history never erased) ## API Endpoints - GET /api/activities/[activityId] - Single activity with rollback eligibility - POST /api/activities/[activityId]/rollback - Execute rollback - GET /api/pages/[pageId]/history - Page version history - GET /api/drives/[driveId]/history - Drive version history (admin) ## UI Components - VersionHistoryPanel - Slide-out panel with timeline and filters - VersionHistoryItem - Activity item with "Restore" action - RollbackConfirmDialog - Confirmation modal with warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: complete rollback handler implementations and fix lint errors - Fully implement rollbackPermissionChange for grant/revoke/update operations - Fully implement rollbackMemberChange for add/remove/role change operations - Fully implement rollbackRoleChange for create/delete/update operations - Fix lint errors: remove unused imports, fix useEffect dependencies - Add package exports for @pagespace/lib/permissions and @pagespace/lib/monitoring - Fix useToast import path to use correct hook location 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add undo AI changes feature for conversations Add ability to undo AI changes from a specific message point: - Preview what will be affected before undoing - Two modes: revert conversation only OR revert with all tool changes - Activity logging for audit compliance New files: - ai-undo-service.ts: preview and execute functions - UndoAiChangesDialog.tsx: confirmation dialog with mode selection - /api/ai/chat/messages/[messageId]/undo: GET preview, POST execute Changes: - Add conversation_undo operations to activity schema - Add message rollback handler to rollback-service - Wire undo button to MessageActionButtons and MessageRenderer 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add missing radio-group UI component Required for UndoAiChangesDialog mode selection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add @radix-ui/react-radio-group dependency Required for radio-group UI component used in UndoAiChangesDialog. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: restore correct @electron/node-gyp resolution in lockfile The previous lockfile had a malformed git SSH URL that broke CI: - Before: git+https://git@github.com:electron/node-gyp.git (broken) - After: https://codeload.github.com/electron/node-gyp/tar.gz/... (works) Restored lockfile and re-ran pnpm install to properly resolve dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add critical rules to CLAUDE.md and fix retention tier order - Add CRITICAL rules for package manager (always pnpm, never npm) - Add CRITICAL rules for database migrations (never manually edit) - Fix retention days: founder=90, business=unlimited (was swapped) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add missing default and rollback index - Add DEFAULT now() for retention_policies.updatedAt column - Add index on activity_logs.rollbackFromActivityId for queries - Create migration 0027_fix_retention_updated_at.sql Addresses PR #118 review issues #10, #20 * fix(lib/permissions): add block scoping and eligibility helper - Wrap switch case declarations in blocks to prevent variable leakage - Add isActivityEligibleForRollback() helper for DRY rollback checks - Export helper for use in history API routes Addresses PR #118 review issues #5, #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lib/monitoring): add rollback fields to ActivityLogInput - Add contentFormat field for content type tracking - Add rollbackFromActivityId for rollback chain references - Pass fields as top-level properties to logActivity Addresses PR #118 review issue #3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): add authorization and resourceType filtering - Add permission check before returning activity details - Implement resourceType query parameter filtering in history routes - Use shared isActivityEligibleForRollback helper - Add case-insensitive resource type matching Addresses PR #118 review issues #6, #7, #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): improve type safety and add transactions - Use Drizzle count() instead of .length for efficient queries - Add operation validation against known valid operations - Fix unsafe null type assertion in RollbackPreview - Re-export RollbackContext type for API route usage - Wrap AI undo mutations in database transaction - Use switch statement for context determination Addresses PR #118 review issues #2, #16, #18, #19, #23 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): add CSRF protection and improve error handling - Use post() with CSRF token for rollback requests - Add error toast for failed preview fetch - Handle non-JSON error responses gracefully - Fix non-existent postWithAuth import to use post - Remove re-throw after toast notification - Fix redundant ternary for buttonSize Addresses PR #118 review issues #1, #8, #11, #17, #22, NEW 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): address schema issues from PR #118 review Critical & Major fixes: - Add missing .defaultNow() to retention_policies.updatedAt (fixes schema/migration mismatch that would cause insert failures) - Add contentFormatEnum for type-safe content format validation (prevents invalid values during rollback parsing) - Add CHECK constraint: retentionDays >= -1 (where -1 = unlimited) - Add rollback source snapshot fields for audit trail preservation: - rollbackSourceOperation: captures source activity type - rollbackSourceTimestamp: captures when source change occurred - rollbackSourceTitle: captures resource title at time of change These denormalized fields survive retention policy deletion, ensuring complete audit trails even when source activities are purged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lib): move rollback fields to top-level in activity logger Fixes Major issue #2 from PR #118 review: - Move rollbackFromActivityId from metadata to top-level field - Move contentFormat from metadata to top-level field - Add rollback source snapshot fields to ActivityLogInput interface - Update logRollbackActivity to accept and pass snapshot fields Fields are now stored in dedicated database columns instead of being nested in the metadata JSONB, enabling proper indexing and querying. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): add transaction support to rollback service Enables atomic rollback operations (Issue #7 from PR #118 review): - Add optional transaction parameter to executeRollback() - Update all internal rollback functions to accept database parameter - Pass rollback source snapshot fields to logRollbackActivity When a transaction is provided, all database operations use it instead of the default db connection, enabling atomic rollback + message deletion in AI undo operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): improve atomicity and context logic in AI undo Fixes Issues #5 and #7 from PR #118 review: Context determination (#5): - Align executeAiUndo context logic with previewAiUndo - Use 'ai_tool' context for pages (all activities here are AI-generated) - Simplifies from switch statement to direct assignment with drive check Transaction atomicity (#7): - Wrap rollbacks AND message deletion in single transaction - Pass transaction to executeRollback for atomic operations - If any operation fails, entire undo is rolled back This ensures users don't end up in inconsistent states where messages are deleted but only some changes were reverted. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): use Zod schema for undo route validation Fixes Issue #6 from PR #118 review: - Replace manual mode validation with Zod schema - Aligns with codebase patterns (see rollback route, history route) - Provides type-safe body parsing with proper TypeScript inference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address CodeRabbit review feedback - Add CHECK constraint to retentionPolicies schema definition (aligns Drizzle schema with existing migration constraint) - Change AI undo to all-or-nothing transaction semantics (any rollback failure aborts entire operation) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add subscriptionTier enum for retention policies - Create subscription_tier pgEnum with 'free', 'pro', 'business', 'founder' - Convert retentionPolicies.subscriptionTier from text to enum - Adds DB-level validation to prevent invalid tier values 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address final CodeRabbit review comments - Add comments explaining rollbackFromActivityId intentionally lacks FK (allows provenance to survive source activity deletion for audit) - Add TODO note for contentSnapshot storage considerations - Optimize message fetching: include createdAt in AiUndoPreview to avoid double database query 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add USING clause for text-to-enum cast PostgreSQL requires explicit cast when converting text column to enum type. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ai): support undo for global assistant messages by checking both messages tables and updating permission logic * fix(ai): resolve lint errors in undo route and tests * test: add contract tests for version history rollback - Add route tests for /api/activities/[activityId]/rollback (12 tests) - Add route tests for /api/pages/[pageId]/history (21 tests) - Add service tests for ai-undo-service (16 tests) with @scaffold label - Add service tests for rollback-service (28 tests) with @scaffold label - Add permission tests for rollback-permissions (69 tests) - Fix undo route test: remove duplicate test expecting wrong status - Add fake timers to history route tests for deterministic dates Per rubric v2: service tests use @scaffold labels for ORM chain mocks pending repository seam refactoring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): add rollback capability to activity views Add "Restore this version" action to activity items in: - ActivityDashboard (middle panel for /dashboard/activity and drive activity) - SidebarActivityTab (right sidebar context-aware activity feed) Changes: - ActivityItem: Add hover dropdown menu with rollback action and confirmation dialog - ActivityTimeline: Pass context and onRollback handler to items - ActivityDashboard: Handle rollback with proper context mapping (user→user_dashboard, drive→drive) - SidebarActivityTab: Add rollback UI with context-aware scoping (page/drive/user_dashboard) Rollback is properly scoped by context to prevent unintended changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add activity logger tests for rollback and undo operations Add compliance tests for: - logRollbackActivity: validates rollback operation logging with source activity reference - logConversationUndo: validates conversation undo logging for both modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(rollback): support create operation rollback and global messages - Add 'create' as rollbackable operation (trash resource to undo creation) - Support both global messages and page chat messages in rollback - Fix AI undo timing to include tool calls from preceding message - Handle message create rollback by deactivating the message 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address PR #118 code review feedback - Fix build failure: replace dynamic db.query[] bracket notation with explicit conditional to resolve TypeScript union type error - Extract checkUndoPermissions() helper to eliminate 31 lines of duplicated permission logic between GET and POST handlers - Add existingPreview parameter to executeAiUndo() to avoid redundant preview computation (was being called twice per request) - Simplify context determination: remove redundant isAiGenerated check since query already filters for it - Update tests to match new 4-parameter executeAiUndo signature - Add clarifying comment explaining partial failure tests document defensive handling (actual impl uses all-or-nothing transaction) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: update rollback-permissions tests for create operation Update test expectations to match the new behavior where 'create' is a rollbackable operation (rolling back a create = trashing the resource). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: reset undo counters on transaction failure When executeAiUndo catches an error, the transaction has been rolled back so no changes were committed. Reset messagesDeleted and activitiesRolledBack to 0 to accurately reflect this. Also simplify the route handler to always return 500 on failure since partial success (207) is now unreachable with all-or-nothing semantics. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove unused params variable in OptimizedViewHeader 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(web): refine AI undo error message to reflect atomic transaction semantics * fix(tests): correct hook test expectations for SWR behavior - useBreadcrumbs: Fix isLoading expectation for null pageId When pageId is null, isLoading correctly returns false (nothing to load) - usePermissions: Fix SWR mock to trigger onSuccess callback isPaused requires hasLoadedRef.current=true, which is set by onSuccess 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: handle all failure cases in AI undo route - Remove `&& result.errors.length > 0` condition so any success:false triggers 500 response, not just failures with non-empty errors - Add test for empty errors array edge case - Enhance usePermissions test to properly validate after onSuccess 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2witstudios
added a commit
that referenced
this pull request
Dec 24, 2025
* feat: add version history and rollback functionality Implement comprehensive version history browsing and rollback capabilities for PageSpace, allowing users to restore resources to previous states. ## Schema Changes - Add 'rollback' operation to activity_operation enum - Add rollbackFromActivityId and contentFormat fields to activity_logs - Create retention_policies table for plan-based history retention ## Core Features - RBAC-based rollback permissions (edit access = rollback access) - Resource-specific rollback handlers (pages, drives, agents, etc.) - Plan-based retention limits (7/30/90/unlimited days) - Rollback creates new activity entry (history never erased) ## API Endpoints - GET /api/activities/[activityId] - Single activity with rollback eligibility - POST /api/activities/[activityId]/rollback - Execute rollback - GET /api/pages/[pageId]/history - Page version history - GET /api/drives/[driveId]/history - Drive version history (admin) ## UI Components - VersionHistoryPanel - Slide-out panel with timeline and filters - VersionHistoryItem - Activity item with "Restore" action - RollbackConfirmDialog - Confirmation modal with warnings 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: complete rollback handler implementations and fix lint errors - Fully implement rollbackPermissionChange for grant/revoke/update operations - Fully implement rollbackMemberChange for add/remove/role change operations - Fully implement rollbackRoleChange for create/delete/update operations - Fix lint errors: remove unused imports, fix useEffect dependencies - Add package exports for @pagespace/lib/permissions and @pagespace/lib/monitoring - Fix useToast import path to use correct hook location 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat: add undo AI changes feature for conversations Add ability to undo AI changes from a specific message point: - Preview what will be affected before undoing - Two modes: revert conversation only OR revert with all tool changes - Activity logging for audit compliance New files: - ai-undo-service.ts: preview and execute functions - UndoAiChangesDialog.tsx: confirmation dialog with mode selection - /api/ai/chat/messages/[messageId]/undo: GET preview, POST execute Changes: - Add conversation_undo operations to activity schema - Add message rollback handler to rollback-service - Wire undo button to MessageActionButtons and MessageRenderer 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add missing radio-group UI component Required for UndoAiChangesDialog mode selection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add @radix-ui/react-radio-group dependency Required for radio-group UI component used in UndoAiChangesDialog. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: restore correct @electron/node-gyp resolution in lockfile The previous lockfile had a malformed git SSH URL that broke CI: - Before: git+https://git@github.com:electron/node-gyp.git (broken) - After: https://codeload.github.com/electron/node-gyp/tar.gz/... (works) Restored lockfile and re-ran pnpm install to properly resolve dependencies. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: add critical rules to CLAUDE.md and fix retention tier order - Add CRITICAL rules for package manager (always pnpm, never npm) - Add CRITICAL rules for database migrations (never manually edit) - Fix retention days: founder=90, business=unlimited (was swapped) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add missing default and rollback index - Add DEFAULT now() for retention_policies.updatedAt column - Add index on activity_logs.rollbackFromActivityId for queries - Create migration 0027_fix_retention_updated_at.sql Addresses PR #118 review issues #10, #20 * fix(lib/permissions): add block scoping and eligibility helper - Wrap switch case declarations in blocks to prevent variable leakage - Add isActivityEligibleForRollback() helper for DRY rollback checks - Export helper for use in history API routes Addresses PR #118 review issues #5, #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lib/monitoring): add rollback fields to ActivityLogInput - Add contentFormat field for content type tracking - Add rollbackFromActivityId for rollback chain references - Pass fields as top-level properties to logActivity Addresses PR #118 review issue #3 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): add authorization and resourceType filtering - Add permission check before returning activity details - Implement resourceType query parameter filtering in history routes - Use shared isActivityEligibleForRollback helper - Add case-insensitive resource type matching Addresses PR #118 review issues #6, #7, #13 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): improve type safety and add transactions - Use Drizzle count() instead of .length for efficient queries - Add operation validation against known valid operations - Fix unsafe null type assertion in RollbackPreview - Re-export RollbackContext type for API route usage - Wrap AI undo mutations in database transaction - Use switch statement for context determination Addresses PR #118 review issues #2, #16, #18, #19, #23 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): add CSRF protection and improve error handling - Use post() with CSRF token for rollback requests - Add error toast for failed preview fetch - Handle non-JSON error responses gracefully - Fix non-existent postWithAuth import to use post - Remove re-throw after toast notification - Fix redundant ternary for buttonSize Addresses PR #118 review issues #1, #8, #11, #17, #22, NEW 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): address schema issues from PR #118 review Critical & Major fixes: - Add missing .defaultNow() to retention_policies.updatedAt (fixes schema/migration mismatch that would cause insert failures) - Add contentFormatEnum for type-safe content format validation (prevents invalid values during rollback parsing) - Add CHECK constraint: retentionDays >= -1 (where -1 = unlimited) - Add rollback source snapshot fields for audit trail preservation: - rollbackSourceOperation: captures source activity type - rollbackSourceTimestamp: captures when source change occurred - rollbackSourceTitle: captures resource title at time of change These denormalized fields survive retention policy deletion, ensuring complete audit trails even when source activities are purged. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(lib): move rollback fields to top-level in activity logger Fixes Major issue #2 from PR #118 review: - Move rollbackFromActivityId from metadata to top-level field - Move contentFormat from metadata to top-level field - Add rollback source snapshot fields to ActivityLogInput interface - Update logRollbackActivity to accept and pass snapshot fields Fields are now stored in dedicated database columns instead of being nested in the metadata JSONB, enabling proper indexing and querying. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): add transaction support to rollback service Enables atomic rollback operations (Issue #7 from PR #118 review): - Add optional transaction parameter to executeRollback() - Update all internal rollback functions to accept database parameter - Pass rollback source snapshot fields to logRollbackActivity When a transaction is provided, all database operations use it instead of the default db connection, enabling atomic rollback + message deletion in AI undo operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(services): improve atomicity and context logic in AI undo Fixes Issues #5 and #7 from PR #118 review: Context determination (#5): - Align executeAiUndo context logic with previewAiUndo - Use 'ai_tool' context for pages (all activities here are AI-generated) - Simplifies from switch statement to direct assignment with drive check Transaction atomicity (#7): - Wrap rollbacks AND message deletion in single transaction - Pass transaction to executeRollback for atomic operations - If any operation fails, entire undo is rolled back This ensures users don't end up in inconsistent states where messages are deleted but only some changes were reverted. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(api): use Zod schema for undo route validation Fixes Issue #6 from PR #118 review: - Replace manual mode validation with Zod schema - Aligns with codebase patterns (see rollback route, history route) - Provides type-safe body parsing with proper TypeScript inference 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address CodeRabbit review feedback - Add CHECK constraint to retentionPolicies schema definition (aligns Drizzle schema with existing migration constraint) - Change AI undo to all-or-nothing transaction semantics (any rollback failure aborts entire operation) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add subscriptionTier enum for retention policies - Create subscription_tier pgEnum with 'free', 'pro', 'business', 'founder' - Convert retentionPolicies.subscriptionTier from text to enum - Adds DB-level validation to prevent invalid tier values 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address final CodeRabbit review comments - Add comments explaining rollbackFromActivityId intentionally lacks FK (allows provenance to survive source activity deletion for audit) - Add TODO note for contentSnapshot storage considerations - Optimize message fetching: include createdAt in AiUndoPreview to avoid double database query 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(db): add USING clause for text-to-enum cast PostgreSQL requires explicit cast when converting text column to enum type. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ai): support undo for global assistant messages by checking both messages tables and updating permission logic * fix(ai): resolve lint errors in undo route and tests * test: add contract tests for version history rollback - Add route tests for /api/activities/[activityId]/rollback (12 tests) - Add route tests for /api/pages/[pageId]/history (21 tests) - Add service tests for ai-undo-service (16 tests) with @scaffold label - Add service tests for rollback-service (28 tests) with @scaffold label - Add permission tests for rollback-permissions (69 tests) - Fix undo route test: remove duplicate test expecting wrong status - Add fake timers to history route tests for deterministic dates Per rubric v2: service tests use @scaffold labels for ORM chain mocks pending repository seam refactoring. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): add rollback capability to activity views Add "Restore this version" action to activity items in: - ActivityDashboard (middle panel for /dashboard/activity and drive activity) - SidebarActivityTab (right sidebar context-aware activity feed) Changes: - ActivityItem: Add hover dropdown menu with rollback action and confirmation dialog - ActivityTimeline: Pass context and onRollback handler to items - ActivityDashboard: Handle rollback with proper context mapping (user→user_dashboard, drive→drive) - SidebarActivityTab: Add rollback UI with context-aware scoping (page/drive/user_dashboard) Rollback is properly scoped by context to prevent unintended changes. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: add activity logger tests for rollback and undo operations Add compliance tests for: - logRollbackActivity: validates rollback operation logging with source activity reference - logConversationUndo: validates conversation undo logging for both modes 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(rollback): support create operation rollback and global messages - Add 'create' as rollbackable operation (trash resource to undo creation) - Support both global messages and page chat messages in rollback - Fix AI undo timing to include tool calls from preceding message - Handle message create rollback by deactivating the message 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: address PR #118 code review feedback - Fix build failure: replace dynamic db.query[] bracket notation with explicit conditional to resolve TypeScript union type error - Extract checkUndoPermissions() helper to eliminate 31 lines of duplicated permission logic between GET and POST handlers - Add existingPreview parameter to executeAiUndo() to avoid redundant preview computation (was being called twice per request) - Simplify context determination: remove redundant isAiGenerated check since query already filters for it - Update tests to match new 4-parameter executeAiUndo signature - Add clarifying comment explaining partial failure tests document defensive handling (actual impl uses all-or-nothing transaction) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test: update rollback-permissions tests for create operation Update test expectations to match the new behavior where 'create' is a rollbackable operation (rolling back a create = trashing the resource). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: reset undo counters on transaction failure When executeAiUndo catches an error, the transaction has been rolled back so no changes were committed. Reset messagesDeleted and activitiesRolledBack to 0 to accurately reflect this. Also simplify the route handler to always return 500 on failure since partial success (207) is now unreachable with all-or-nothing semantics. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: remove unused params variable in OptimizedViewHeader 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(web): refine AI undo error message to reflect atomic transaction semantics * fix(tests): correct hook test expectations for SWR behavior - useBreadcrumbs: Fix isLoading expectation for null pageId When pageId is null, isLoading correctly returns false (nothing to load) - usePermissions: Fix SWR mock to trigger onSuccess callback isPaused requires hasLoadedRef.current=true, which is set by onSuccess 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: handle all failure cases in AI undo route - Remove `&& result.errors.length > 0` condition so any success:false triggers 500 response, not just failures with non-empty errors - Add test for empty errors array edge case - Enhance usePermissions test to properly validate after onSuccess 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix: resolve AI chat undo feature not working The undo feature was always showing "Failed to undo changes" due to incorrect usage of the post() helper from auth-fetch. The post() function: - Returns parsed JSON on success (not a Response object) - Throws an error on non-2xx responses Components were incorrectly checking res.ok (undefined on parsed JSON) and calling res.json() on already-parsed objects, causing the error branch to always trigger. Changes: - Fix UndoAiChangesDialog to properly use post() - await and catch errors - Fix ActivityDashboard, SidebarActivityTab, VersionHistoryPanel (same pattern) - Update page-write-tools activity logging to pass previousValues for rollback support (replace_lines, rename_page, trash/restore, move_page, edit_sheet_cells now store original state for proper undo) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2witstudios
added a commit
that referenced
this pull request
Feb 15, 2026
Updated GitHub Project with all completed issues: - Marked 14 additional issues as Done via gh CLI - Project status: 20/30 Done (67%) Remaining 10 issues: - 5 Remotion compositions (deferred - awaiting UI parity) - 5 requiring external resources (auth, Google, app stores) Extra pages implemented beyond original project scope: - /blog with 4 posts - /faq - /docs with getting-started guide - /changelog Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2witstudios
added a commit
that referenced
this pull request
Feb 17, 2026
…n, and auth isolation (#694) * feat(marketing): Complete site architecture setup (#638) - Configure shadcn/ui with 55+ components - Copy public assets (favicons, icons, manifest) from web app - Create .env.example with marketing site configuration - Fix lint errors in combobox component - Create tracking docs (PROJECT_MIRROR.md, PROGRESS.md, SESSION_LOG.md) - Create ARCHITECTURE.md documenting marketing site structure Issue #638 acceptance criteria met: - Next.js 15 App Router configured - Tailwind + shadcn/ui working - TypeScript strict mode enabled - Environment variables documented - Build passes with no errors Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(marketing): Add sitemap.xml and update robots.txt (#642) - Create dynamic sitemap.ts with all planned marketing routes - Include 12 URLs: /, /pricing, /downloads, /tour, /integrations, /faq, /changelog, /docs/*, /blog - Update robots.txt for marketing site (disallow /screenshots/, /api/, /_next/) - Configure proper priorities and change frequencies Issue #642 acceptance criteria met: - sitemap.xml generated at build time - All public pages included - robots.txt allows crawling - Sitemap accessible at /sitemap.xml - No private/auth pages in sitemap Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(marketing): Add comprehensive SEO metadata and OG images (#644) - Create src/lib/metadata.ts with reusable SEO helpers - Add createMetadata() for per-page metadata generation - Define siteMetadata with full OG, Twitter, icons, manifest config - Create pageMetadata presets for all planned marketing pages - Update layout.tsx with comprehensive site-wide metadata - Add dynamic /og-image.png route for Open Graph images - Configure theme-color meta for light/dark modes Issue #644 acceptance criteria met: - Every page has unique title/description (via metadata presets) - Open Graph images for all pages (dynamic route) - Twitter cards working (configured in siteMetadata) - Canonical URLs set (via alternates.canonical) - No duplicate meta tags Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(marketing): Add Schema.org structured data (#643) - Create src/lib/schema.tsx with comprehensive JSON-LD schemas - Add Organization schema (site-wide in layout.tsx) - Add WebSite schema with search action - Add WebApplication schema for landing page - Add Product schema with all 4 pricing tiers - Add SoftwareApplication schema for downloads - Add FAQPage schema helper (createFAQSchema) - Add Article schema helper (createArticleSchema) - Add BreadcrumbList schema helper - Add JsonLd component for rendering scripts Issue #643 acceptance criteria met: - Organization schema on all pages - WebApplication schema on landing - Product schema with offers - FAQPage schema ready for FAQ page - Article schema ready for blog posts Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(marketing): Implement landing page Hero section (#646) - Replace screenshot generator with full marketing landing page - Create Hero section with core value proposition - Headline: "You, your team, and AI—working together" - AI-native badge - Clear subheadline - Get Started / View Pricing CTAs - Desktop/mobile app availability - Add full UI mockup showing PageSpace interface - Sidebar with navigation - Document editor view - AI Assistant panel - Add sticky navigation header - Add features preview section - Add minimal footer with navigation - Include WebApplication schema JSON-LD - Use proper metadata from lib/metadata.ts Issue #646 acceptance criteria met: - Clear value proposition in <5 seconds - CTAs prominent and accessible - Responsive across all breakpoints - Accessible design Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(marketing): Add AI architecture section to landing page (#647) - Add comprehensive AI Architecture section explaining: - Global Assistant (personal, cross-workspace AI) - Page Agents (file tree, custom prompts, conversation history) - Nested Context (hierarchical awareness) - Team AI (multi-user collaboration) - Create visual file tree mockup showing: - Global Assistant at top level - Project-level AI agents - Document hierarchy with context flow - Add ICP example quote from founder perspective - Clearly differentiate from ChatGPT/Notion AI approach Issue #647 acceptance criteria met: - Clear explanation of Global vs Page agents - Visual shows context hierarchy - Differentiates from ChatGPT/Notion AI - ICP example resonates Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Complete Landing Page Redesign epic + Remotion setup (#648-653) Landing Page sections implemented: - Documents section with document editor mockup and AI suggestions - Channels + DMs section with @mention AI demonstration - Tasks section with AI assignee and rollup visualization - Calendar section with unified multi-source view - Final CTA section with trust signals and quick links - Enhanced footer with categorized navigation Remotion Video System setup: - Installed Remotion 4.x with Tailwind support - Created Root.tsx with DESIGN_TOKENS and theme system - Sample and Hero compositions with light/dark variants - Render scripts for MP4 output - Separate tsconfig.remotion.json for Remotion build - Full documentation in remotion/README.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add Downloads and Pricing pages (#659-660, #663-664) Downloads page (/downloads): - Desktop downloads for macOS (Silicon/Intel), Windows, Linux (AppImage/deb) - Mobile apps section with iOS TestFlight and Android Beta links - System requirements for all platforms - Auto-update information and version display - Links to changelog Pricing page (/pricing): - 4 pricing tiers (Free, Pro, Founder, Business) with feature cards - Full feature comparison table with tooltips - Enterprise section with contact CTA - FAQ preview section Remotion partial work (deferred pending UI parity): - DocumentEditing and Channels compositions created but not complete 14 static pages now build successfully. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Add marketing pages: tour, integrations, blog, FAQ, docs, changelog Complete implementation of 10 marketing site pages: Tour (/tour): - 5-step product tour workflow - AI Architecture overview section - Visual mockups with placeholders Integrations (/integrations): - MCP Servers showcase with 6 servers - Native integrations section - Developer section with API documentation Blog (/blog, /blog/[slug]): - Blog index with category filtering - 4 initial blog posts with full content - Newsletter signup CTA FAQ (/faq): - 20 FAQs across 6 categories - Expandable details/summary UI Documentation (/docs, /docs/getting-started): - Documentation hub with search - Getting started guide with 5 steps Changelog (/changelog): - Version history with 5 releases - Timeline UI with change type badges Also: - Updated sitemap.ts with all new routes - Updated tracking files (PROGRESS.md, SESSION_LOG.md, PROJECT_MIRROR.md) Build: 25 static pages, all passing Issues completed: #665, #666, #667, #668, #669, #670, #671, #672, #673, #674, #641 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Sync GitHub Project #5 status - 20 issues now Done Updated GitHub Project with all completed issues: - Marked 14 additional issues as Done via gh CLI - Project status: 20/30 Done (67%) Remaining 10 issues: - 5 Remotion compositions (deferred - awaiting UI parity) - 5 requiring external resources (auth, Google, app stores) Extra pages implemented beyond original project scope: - /blog with 4 posts - /faq - /docs with getting-started guide - /changelog Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * Update PROJECT_MIRROR.md notes to reflect current status * feat(marketing): Redesign landing page for visual parity with real app + add auth pages Overhaul the marketing site to pixel-match the actual PageSpace UI, add a branded oklch color system, extract SiteNavbar, build login/signup auth flow, and add the motion library for animations. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(marketing): Redesign Page Tree section, extract shared components, clean up UI - Rebuild "AI Architecture" section as "Everything is a page" with real sidebar mock matching actual PageSpace UI (drive switcher, nav, search, page tree with nesting) - Add deeper nesting (channel with child pages) to show semantic parent/child - Rewrite feature cards to 3 focused cards: Everything is a Page, Context is Structure, AI at Every Level - Extract SiteFooter component (full + compact variants) used across all 12 pages - Fix logo everywhere: replace Sparkles icon with real PageSpace logo - Update SiteNavbar: add centered nav links, replace Home icon with logo, remove sidebar/nav buttons - Remove all section header badges and testimonial cards - Remove "Free tier / No credit card / Cancel anytime" from CTA section - Remove unused Globe import Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * feat(marketing): Complete non-Remotion marketing site work - Register Channels Remotion composition (light/dark variants) - Port privacy policy and terms of service pages from main app - Add contact page with isolated Resend email integration (no DB) - Delete main app's public /api/contact route (admin route kept) - Fix dead footer links: remove About, Careers, API Reference - Remove auth pages, redirect all auth links to main app - Add Google One Tap passive host component - Add Google Search Console verification placeholder - Add downloads "Coming Soon" state + deep link scaffolding - Clean up "Coming Soon" placeholder text - Replace app.pagespace.ai fallbacks with pagespace.ai Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(marketing): Address PR #694 review comments (9 fixes) - Add "use client" directive to navigation-menu.tsx for Radix hooks - Use shared pageMetadata for terms/privacy pages instead of inline createMetadata - Remove SearchAction from JSON-LD schema (no /search page exists) - Fix HSL color opacity in Remotion DocumentEditing (withOpacity helper replaces broken hex concatenation) - Fix render-videos.ts progress logging and wire enableTailwind into webpack override - Remove unimplemented /docs/api and /docs/mcp from sitemap - Point broken /docs/* links to /docs fallback across integrations, docs, and getting-started pages - Replace copy-pasted inline headers with SiteNavbar in 7 pages - Replace line-by-line blog markdown parser with react-markdown + remark-gfm Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(marketing): Address 21 code review findings ESM: Add --esm to remotion scripts, polyfill __dirname/fileURLToPath Blog: Extract blogPosts to data.ts, create ShareButtons client component, add openGraph.url Docs: Fix duplicate React keys, dedup Popular Articles, replace search input with button, shared metadata for getting-started, Coming Soon cards Integrations: Replace div-based curl snippet with semantic pre/code Legal: Add LEGAL_LAST_UPDATED constant for terms and privacy, Discord link attrs Tour: Use map index instead of fragile step.number coupling Navigation: Remove unnecessary cn() wrapper, extract viewportFalseClasses Schema: Remove invalid downloadUrl, sanitize JsonLd XSS, extract SOFTWARE_VERSION, strip nested @context from embedded organizationRef * fix(marketing): Address follow-up review findings Fix broken /docs/mcp markdown link in blog data Add try/catch to clipboard API in ShareButtons Add comingSoon flag to docs placeholder items, render as non-clickable Mark SDK Libraries and Webhook Events as coming soon on integrations page Fix double title suffix: createMetadata no longer appends '| PageSpace' (layout template handles it) Extract shared APP_URL constant from metadata.ts, deduplicate across 12 files Tighten JsonLd prop type from object to Record<string, unknown> Add rel='noopener' to external CTA anchor on blog page Add dev env comment for SITE_URL/APP_URL fallback values in schema.tsx --------- Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Testing
https://chatgpt.com/codex/tasks/task_e_68d31a1667208320a446d987b320fc63