- Register missing shape types in Automerge schema (CalendarEvent, HolonBrowser, PrivateWorkspace, GoogleItem, WorkflowBlock)
- Improve connections API error handling to detect HTML responses gracefully
- Clean up Vite config debug logs
- Add static PWA manifest and link to index.html for proper manifest serving
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added HOLON_ENABLED feature flag (set to false) to completely disable Holon functionality
- HoloSphereService methods now return early with default values when disabled
- Removed all console.log/error output when Holon is disabled
- HolonShapeUtil shows "Feature Disabled" message when flag is false
- HolonBrowser shows disabled message instead of attempting connections
- Code preserved for future Nostr integration re-enablement
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Added missing Calendar and Drawfast shapes to the automerge store
schema registration to fix ValidationError when using these tools.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implements a visual workflow builder with:
- WorkflowBlockShapeUtil: Visual blocks with typed input/output ports
- WorkflowBlockTool: Click-to-place tool for adding blocks
- Block registry with 20+ blocks (triggers, actions, conditions, transformers, AI, outputs)
- Port validation and type compatibility checking
- WorkflowPropagator for real-time data flow between connected blocks
- Workflow executor for manual execution with topological ordering
- WorkflowPalette UI sidebar with searchable block categories
- JSON serialization for workflow export/import
- Workflow templates (API request, LLM chain, conditional)
Blocks are accessible via "Workflow Blocks" button in toolbar dropdown.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The Flowy workflow files have TypeScript errors that prevent builds.
Removing them entirely until they can be properly fixed and tested.
Files removed:
- src/components/workflow/
- src/css/workflow.css
- src/lib/workflow/
- src/propagators/WorkflowPropagator.ts
- src/shapes/WorkflowBlockShapeUtil.tsx
- src/tools/WorkflowBlockTool.ts
The commented-out imports in Board.tsx and CustomToolbar.tsx remain
as documentation of what needs to be re-added.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add CalendarShapeUtil with view tabs (Browser/Widget/Year)
- Add CalendarTool for placing calendar on canvas
- Add CalendarEventShapeUtil for spawning event cards
- Add CalendarPanel component with month/week views
- Add YearViewPanel component with 12-month grid
- Add useCalendarEvents hook for fetching encrypted calendar data
- Single keyboard shortcut (Ctrl+Alt+K) with in-shape view switching
- Auto-resize when switching between views
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove conflicting height calc in contentStyle (was conflicting with flex:1)
- Use minHeight:0 to allow proper flex shrinking
- Add debug logging for pin toggle to diagnose pin button issues
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Added adminRequestError state to track request failures
- Parse and display server error messages to user
- Show red error button with retry option on failure
- Display error message below button explaining what went wrong
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Use explicit background colors instead of CSS variables
- Add dark mode detection to ShareBoardButton
- Prevents see-through dropdowns
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove anonymous viewer popup (anonymous users can now edit)
- Mobile menu consolidation: gear icon with all menus combined
- Connection status notifications below MI bar (Offline use, Reconnecting, Live)
- Network graph panel starts collapsed on mobile
- MI bar positioned at top on mobile
Deployment:
- Add docker-compose.dev.yml for staging.jeffemmett.com (dev branch)
- Update production docker-compose.yml to remove staging route
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Downgrade three.js from 0.182 to 0.168 to fix customDepthMaterial
getter-only property breaking change (drei issue #2403)
- Add stable useCallback for modal close handler to prevent
reference instability
- Improve ESC key handler with ref pattern and capture phase
to ensure reliable modal closing
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
3D Visualization (NetworkGraph3D):
- Three.js force-directed graph with React Three Fiber
- Trust-level shells: trusted (inner), connected (middle), unconnected (outer)
- Node sizing proportional to decision power (incoming connections)
- Animated particle flows along edges showing delegation direction
- Zoom to user with smooth camera animation
- Orbit controls for 3D navigation (drag rotate, scroll zoom)
Broadcast Mode:
- "View as User" button syncs camera to selected user's view
- Visual indicator at top: "Viewing as [User] - ESC to exit"
- ESC or X key to stop following
- URL deep linking with ?followId parameter
UI Improvements:
- Panel now stacks directly above tldraw minimap
- Matched width (200px) with minimap for alignment
- Fixed D3 simulation stability (was reinitializing every render)
- 3-state display: minimized icon, normal panel, maximized 3D modal
Dependencies:
- three@^0.182.0
- @react-three/fiber@8.17.10 (React 18 compatible)
- @react-three/drei@9.114.3
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Pinned shapes should only stay fixed in screen position, not fixed in
visual size. The CSS transform: scale() was causing shapes to appear
differently sized when pinned.
Now pinned shapes:
- Stay at a fixed screen position (don't move when panning)
- Scale normally with zoom (get bigger/smaller like other shapes)
- Don't change appearance when pin is toggled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Pinned shapes now stay exactly the same size visually during zoom
- Uses CSS transform scale instead of changing w/h props
- Content inside shapes renders identically at all zoom levels
- Stores pinnedAtZoom in shape.meta for reference
- Returns to original position smoothly when unpinned
- Removed size-changing logic that was causing content reflow issues
The transform approach ensures text, UI elements, and all content
inside pinned shapes remain pixel-perfect regardless of canvas zoom.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Preserve tldraw-user-id-* and crypto keys on logout (prevents duplicate cursors)
- Add session-logged-in event for immediate tool enabling after login
- Add session-cleared event for component state cleanup
- Clear only session-specific data (permissions, graph cache, room ID)
- CryptIDDropdown: reset connections state on logout
- useNetworkGraph: clear graph cache on logout
The key fix is preserving tldraw user IDs across login/logout cycles.
Previously, clearing these IDs caused each login to create a new presence
record while old ones persisted in Automerge, resulting in stacked cursors.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove separate BoardSettingsDropdown button from UI panel
- Add board protection toggle and editor management to existing settings dropdown
- Show protection section only for admins (board owner or global admin)
- Add ability to toggle view-only mode for protected boards
- Add editor management UI with invite and remove functionality
- Fix TypeScript type annotations for API responses
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
NEW PERMISSION MODEL:
- All users (including anonymous) can now EDIT by default
- Boards can be marked as "protected" by admin - only listed editors can edit
- Global admins (jeffemmett@gmail.com) have admin on ALL boards
- Added BoardSettingsDropdown with view-only toggle for admins
Backend changes:
- Added is_protected column to boards table
- Added global_admins table
- New getEffectivePermission logic prioritizes: token > global admin > owner > protection status
- New API endpoints: /auth/global-admin-status, /admin/request, /boards/:id/info, /boards/:id/editors
- Admin request sends email via Resend API
Frontend changes:
- BoardSettingsDropdown component with protection toggle and editor management
- Updated AuthContext and Board.tsx to default to 'edit' permission
- isReadOnly now only true for protected boards where user is not an editor
Task: task-052
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add "(you)" indicator on tooltip when hovering current user's node
- Ensure current user always appears in graph even with no connections
- Add new participants immediately to graph (no 30s delay)
- Implement "leave" message protocol for presence cleanup:
- Client sends leave message before disconnecting
- Server broadcasts leave to other clients on disconnect
- Clients remove presence records on receiving leave
- Generate consistent user colors from CryptID username (not session ID)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When the browser reloads without network connectivity, the canvas now
automatically loads from local IndexedDB storage and renders the last
known state.
Changes:
- Board.tsx: Updated render condition to allow rendering when offline
with local data (isOfflineWithLocalData flag)
- useAutomergeStoreV2: Added isNetworkOnline parameter and offline fast
path that immediately loads records from Automerge doc without waiting
for network patches
- useAutomergeSyncRepo: Passes isNetworkOnline to useAutomergeStoreV2
- ConnectionStatusIndicator: Updated messaging to clarify users are
viewing locally cached canvas when offline
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add dropdown menu when clicking user nodes in network graph with options:
- Connect with <username>
- Navigate to <username> (pan to cursor)
- Screenfollow <username> (follow camera)
- Open <username>'s profile
- Fix tool visibility for logged-in users (timing issue with read-only mode)
- Fix 401 errors by correcting localStorage key from 'cryptid_session' to 'canvas_auth_session'
- Remove "(anonymous)" suffix from usernames in tooltips
- Simplify node colors to use user's profile/presence color
- Clear permission cache on logout to prevent stale state
- Various UI improvements to auth components and network graph
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add maximize/fullscreen button to standardized header bar
- Create useMaximize hook for shape utils to enable fullscreen
- Shape fills viewport when maximized, restores on Esc or toggle
- Implement on ChatBoxShapeUtil as example (other shapes can add easily)
- Button shows ⤢ for maximize, ⊡ for exit fullscreen
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add InviteDialog component with tabbed interface for sharing boards
- Add ShareBoardButton component to toolbar
- Integrate qrcode.react for QR code generation
- Implement Web NFC API for NFC tag writing
- Add placeholder for audio connect feature (coming soon)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Social Network Graph:
- Dark/black theme with semi-transparent background
- Arrow markers on edges showing connection direction
- Color-coded arrows: grey (default), yellow (connected), green (trusted)
- Updated header, stats, and icon button colors for dark theme
MI (Mycelial Intelligence) Bar:
- Responsive width: full width on mobile, percentage on narrow, fixed on desktop
- Position: moves to bottom on mobile (above toolbar), stays at top on desktop
- Smooth transitions when resizing
- Smaller max height on mobile (300px vs 400px)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Network Graph:
- Add graceful fallback when API returns 401 or other errors
- Falls back to showing room participants as nodes
- Prevents error spam in console for unauthenticated users
Map Shape (linter changes):
- Add isFetchingNearby state for loading indicator
- Improve addAnnotation to accept name/color options
- Add logging for Find Nearby debugging
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
UI Changes:
- Add CryptIDDropdown component with Google integration under Integrations
- Remove user presence avatars (moved to network graph)
- New top-right layout: CryptID -> Star -> Gear dropdown -> Question mark
- Settings gear shows dropdown with dark mode toggle + All Settings link
- Network graph label changed to "Social Network"
- Network graph shows for all users including anonymous
- Solo users see themselves as a lone node
Map Shape Fixes:
- Fix stale closure bug: tool clicks now work using activeToolRef
- Fix wheel scroll: native event listener prevents tldraw capture
- Add pointerEvents: 'auto' to map container for proper mouse interaction
Bug Fix:
- Add Map shape sanitization in AutomergeToTLStore for pinnedToView/isMinimized
- Prevents "Expected boolean, got undefined" errors on old Map data
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Shows all collaborators currently on the canvas with their connection status:
- Green border: Trusted (edit access)
- Yellow border: Connected (view access)
- Grey border: Not connected
Users can:
- Add unconnected users as Connected or Trusted
- Upgrade Connected users to Trusted
- Downgrade Trusted users to Connected
- Remove connections
Also fixes TypeScript errors in networking module.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add permission fetching and state management in Board.tsx
- Fetch user's permission level when board loads
- Set tldraw to read-only mode when user has 'view' permission
- Show AnonymousViewerBanner for unauthenticated users
- Banner prompts CryptID sign-up with your specified messaging
- Update permission state when user authenticates
- Wire up permission API routes in worker/worker.ts
- GET /boards/:boardId/permission
- GET /boards/:boardId/permissions (admin)
- POST /boards/:boardId/permissions (admin)
- DELETE /boards/:boardId/permissions/:userId (admin)
- PATCH /boards/:boardId (admin)
- Add X-CryptID-PublicKey to CORS allowed headers
- Add PUT, PATCH, DELETE to CORS allowed methods
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Phase 1 of user permissions feature:
- Add board permissions schema to D1 database
- boards table with owner, default_permission, is_public
- board_permissions table for per-user permissions
- Add permission types (PermissionLevel) to worker and client
- Implement permission API handlers in worker/boardPermissions.ts
- GET /boards/:boardId/permission - check user's permission
- GET /boards/:boardId/permissions - list all (admin only)
- POST /boards/:boardId/permissions - grant permission (admin)
- DELETE /boards/:boardId/permissions/:userId - revoke (admin)
- PATCH /boards/:boardId - update board settings (admin)
- Update AuthContext with permission fetching and caching
- fetchBoardPermission() - fetch and cache permission for a board
- canEdit() - check if user can edit current board
- isAdmin() - check if user is admin for current board
- Create AnonymousViewerBanner component with CryptID signup prompt
- Add CSS styles for anonymous viewer banner
- Fix automerge sync manager to flush saves on peer disconnect
Permission levels:
- view: Read-only, cannot create/edit/delete shapes
- edit: Can modify board contents
- admin: Full access + permission management
Next steps:
- Integrate with Board component for read-only mode
- Wire up permission checking in Automerge sync
- Add permission management UI for admins
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add src/open-mapping/** to tsconfig exclude (21K lines, to harden later)
- Delete MapShapeUtil.backup.tsx
- Fix ConnectionStatus type in OfflineIndicator
- Fix data type assertions in MapShapeUtil (routing/search)
- Fix GoogleDataService.authenticate() call with required param
- Add ts-expect-error for Automerge NetworkAdapter 'ready' event
- Add .wasm?module type declaration for Wrangler imports
- Include GPS location sharing enhancements in MapShapeUtil
TypeScript now compiles cleanly. Vite build needs NODE_OPTIONS for memory.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add VisibilityChangeModal for confirming visibility changes
- Add VisibilityChangeManager to handle events and drag detection
- GoogleItem shapes now dispatch visibility change events on badge click
- Support both local->shared and shared->local transitions
- Auto-detect when GoogleItems are dragged outside PrivateWorkspace
- Session storage for "don't ask again" preference
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- PrivateWorkspaceShapeUtil: Frosted glass container shape with:
- Dashed indigo border for visual distinction
- Pin/collapse/close buttons in header
- Dark mode support
- Position/size persistence to localStorage
- Helper functions for zone detection
- PrivateWorkspaceTool: Tool for creating workspace zones
- usePrivateWorkspace hook:
- Creates/toggles workspace visibility
- Listens for 'add-google-items-to-canvas' events
- Places items inside the private zone
- Persists visibility state
- PrivateWorkspaceManager: Headless component that manages
workspace lifecycle inside Tldraw context
Items added from GoogleExportBrowser will now appear in the
Private Workspace zone as placeholder text shapes (Phase 4
will add proper GoogleItemShape with visual badges).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Rename component file and interface for consistent naming
- Update all imports and state variables in UserSettingsModal
- Better reflects the purpose as a data export browser
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Phase 2 of Data Sovereignty Zone implementation:
- Create GoogleDataBrowser component with service tabs (Gmail, Drive, Photos, Calendar)
- Searchable item list with checkboxes for multi-select
- Select All/Clear functionality
- Dark mode support with consistent styling
- "Add to Private Workspace" button
- Privacy note explaining local-only encryption
- Emits 'add-google-items-to-canvas' event for Board.tsx integration
Integration with UserSettingsModal:
- Import and render GoogleDataBrowser when "Open Data Browser" clicked
- Handler for adding selected items to canvas
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Bring in all the latest changes from main including:
- Index validation and migration for tldraw shapes
- UserSettingsModal with integrations tab
- CryptID authentication updates
- AI services (image gen, video gen, mycelial intelligence)
- Automerge sync improvements
- Various UI improvements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Core modules:
- encryption.ts: WebCrypto AES-256-GCM, HKDF key derivation, PKCE utilities
- database.ts: IndexedDB schema for gmail, drive, photos, calendar
- oauth.ts: OAuth 2.0 PKCE flow with encrypted token storage
- share.ts: Create tldraw shapes from encrypted data
- backup.ts: R2 backup service with encrypted manifest
Importers:
- gmail.ts: Gmail import with pagination and batch storage
- drive.ts: Drive import with folder navigation, Google Docs export
- photos.ts: Photos thumbnail import (403 issue pending investigation)
- calendar.ts: Calendar import with date range filtering
Test interface at /google route for debugging OAuth flow.
Known issue: Photos API returning 403 on some thumbnail URLs - needs
further investigation with proper OAuth consent screen setup.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add router rules for jeffemmett.com and www.jeffemmett.com
- Keep staging.jeffemmett.com for testing
- Preparing for migration from Cloudflare Pages to Docker deployment
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add pin functionality to ImageGen and VideoGen shapes
- Refactor ImageGen to use StandardizedToolWrapper with tags support
- Update StandardizedToolWrapper: grey tags, fix button overlap, improve header drag
- Fix index validation in AutomergeToTLStore for old format indices
- Update wrangler.toml with latest compatibility date and RunPod endpoint docs
- Refactor VideoGen to use captured editor reference for consistency
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Hardcoded fallback values for Ollama and RunPod text endpoints so
that all users have access to AI features without needing to
configure their own API keys:
- Ollama: defaults to https://ai.jeffemmett.com (Netcup AI Orchestrator)
- RunPod Text: defaults to pre-configured vLLM endpoint
This ensures Mycelial Intelligence works for everyone out of the box.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Holon Shape Improvements:
- Add H3 cell ID validation before connecting to Holosphere
- Extract coordinates and resolution from H3 cell IDs automatically
- Improve data rendering with proper lens/item structure display
- Add "Generate H3 Cell" button for quick cell ID creation
- Update placeholders and error messages for H3 format
- Fix HolonBrowser validation and placeholder text
Geometry Error Fix:
- Add try-catch in ClickPropagator.eventHandler for shapes with invalid paths
- Add try-catch in CmdK for getShapesAtPoint geometry errors
- Prevents "No nearest point found" crashes from corrupted draw/line shapes
Offline Persistence:
- Add IndexedDB storage adapter for Automerge documents
- Implement document ID mapping for room persistence
- Merge local and server data on reconnection
- Support offline editing with automatic sync
Other Changes:
- Update .env.example with Ollama and RunPod configuration
- Add multmux Docker configuration files
- UI styling improvements for toolbar and share zone
- Remove auto-creation of MycelialIntelligence shape (now permanent UI bar)
- Various shape utility minor fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Mycelial Intelligence UI refactor:
- Created permanent floating bar at top of screen (MycelialIntelligenceBar.tsx)
- Bar stays fixed and doesn't zoom with canvas
- Collapses when clicking outside
- Removed from toolbar tool menu
- Added deprecated shape stub for backwards compatibility with old boards
- ImageGen RunPod fix:
- Changed from async /run to sync /runsync endpoint
- Fixed output parsing for output.images array format with base64
- Other updates:
- Added FocusLockIndicator and UserSettingsModal UI components
- mulTmux server and shape updates
- Automerge sync and store improvements
- Various CSS and UI refinements
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Updates to collaborative terminal integration and various shape
improvements across the canvas.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add @automerge/automerge-repo-storage-indexeddb for local persistence
- Create documentIdMapping utility to track roomId → documentId in IndexedDB
- Update useAutomergeSyncRepo with offline-first loading strategy:
- Load from IndexedDB first for instant access
- Sync with server in background when online
- Track connection status (online/offline/syncing)
- Add OfflineIndicator component to show connection state
- Integrate offline indicator into Board component
Documents are now cached locally and available offline. Automerge CRDT
handles conflict resolution when syncing back online.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>