Skip to content

Conversation

@khaliqgant
Copy link
Collaborator

@khaliqgant khaliqgant commented Jan 6, 2026

Summary

This PR includes multiple architectural improvements spanning auth revocation handling, per-user credential storage, project groups management, and free tier cost optimizations.

Includes #87


1. Auth Revocation Detection for Workspace Agents

New Files:

  • src/wrapper/auth-detection.ts - Pattern detection for auth errors
  • docs/auth-revocation-handling.md - Design documentation

Modified:

  • src/wrapper/pty-wrapper.ts - Integration with pty wrapper
  • src/wrapper/tmux-wrapper.ts - Integration with tmux wrapper

What it does:
When CLI tools (Claude, Codex, etc.) lose authentication due to session limits:

  • Detects auth revocation patterns in CLI output
  • Sends auth_revoked message to daemon
  • Emits auth_revoked event for listeners
  • Tracks auth state with throttled checking

2. Per-User Credential Storage on Workspace Volumes

New Files:

  • src/daemon/user-directory.ts - UserDirectoryService for managing per-user directories
  • src/daemon/user-directory.test.ts - Tests

Modified:

  • deploy/workspace/entrypoint.sh - Sets HOME to user-specific directory, fixes volume permissions
  • src/cloud/provisioner/index.ts - Adds WORKSPACE_OWNER_USER_ID to all provisioners

Structure:

/data/
└── users/
    └── {userId}/
        ├── .claude/
        ├── .codex/
        └── .config/gcloud/

Why: Enables multi-user workspaces where different users have their own CLI credentials on shared workspaces. Credentials persist across restarts via Fly.io volumes.

Fix: Also fixes Fly.io permission issue - fresh volumes are root-owned, entrypoint now chowns before dropping privileges.


3. Project Groups CRUD API and Frontend

New Files:

  • src/cloud/api/coordinators.ts - Complete CRUD routes

API Endpoints:

Method Route Description
GET /api/project-groups List all groups with repositories
POST /api/project-groups Create new group
PATCH /api/project-groups/:id Update group
DELETE /api/project-groups/:id Delete group
POST /api/project-groups/:id/repositories Add repos to group
DELETE /api/project-groups/:id/repositories/:repoId Remove repo
PUT /api/project-groups/reorder Reorder groups

Modified:

  • src/dashboard/react-components/CoordinatorPanel.tsx - Full CRUD UI
  • src/dashboard/react-components/App.tsx - Workspace settings link

4. Free Tier Cost Optimizations

New Files:

  • src/cloud/services/compute-enforcement.ts - Cron service for enforcing limits
  • src/dashboard/react-components/UsageBanner.tsx - Usage display component

Modified:

  • src/cloud/provisioner/index.ts - Plan-based instance sizing, graceful resize
  • src/cloud/api/billing.ts - Admin bypass, workspace resizing on upgrade
  • src/cloud/config.ts - Admin users config
  • src/cloud/db/drizzle.ts - findByPlan() method
  • src/cloud/server.ts - Compute enforcement service startup
  • src/cloud/services/index.ts - Export compute enforcement

Features:

Feature Description
Smaller free tier instances Free: 1 CPU/1GB ($7/mo), Paid: 2 CPU/2GB ($15/mo)
Compute enforcement cron Runs every 15 mins, warns at 80%, stops at 100%
Usage banner Shows remaining hours, upgrade CTA
Admin user system ADMIN_USERS env var bypasses Stripe
Graceful resize Running workspaces: skip_launch: true, applies on next restart
Billing fix No more hanging for free users without Stripe customer ID

Test Plan

  • Test auth revocation detection with Claude CLI session limits
  • Verify per-user directories created correctly on fresh workspace
  • Test project groups CRUD operations in coordinator panel
  • Verify free tier gets 1GB instance, paid gets 2GB
  • Test compute enforcement stops workspace at 5-hour limit
  • Test admin user bypass for Stripe checkout
  • Verify graceful resize doesn't disrupt running agents

khaliqgant and others added 9 commits January 6, 2026 15:58
When Claude (or other AI CLIs) authentication is revoked due to session
limits (user auth elsewhere), the wrapper now detects this and:
- Sends auth_revoked message to daemon
- Emits auth_revoked event for listeners
- Tracks auth state with throttled checking

New files:
- src/wrapper/auth-detection.ts - Auth error pattern detection
- docs/auth-revocation-handling.md - Design documentation

This is the first part of auth revocation handling. Still needed:
- Re-authentication flow
- Dashboard UI notification
- Pre-auth warning about session limits

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Enable multi-user workspaces by storing credentials in user-specific
directories on the persistent /data volume.

Changes:
- Add UserDirectoryService for managing /data/users/{userId}/ structure
- Add WORKSPACE_OWNER_USER_ID to all provisioners (Fly.io, Railway, Docker)
- Update entrypoint.sh to set HOME to user-specific directory on /data
- All provider credentials (.claude/, .codex/, .config/gcloud/) now stored per-user
- Credentials persist across workspace restarts via Fly.io volume

Structure:
/data/
└── users/
    └── {userId}/
        ├── .claude/
        ├── .codex/
        └── .config/gcloud/

This enables future multi-user support where different users can have
their own CLI credentials on shared workspaces.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Fresh Fly.io volumes are root-owned. The entrypoint was dropping
privileges before fixing permissions, causing mkdir failures when
setting up per-user directories on /data.

Fix: chown /data and /workspace BEFORE dropping to workspace user.

This likely fixes "Proxy not finding machines to route requests" errors
where the container was failing to start due to permission denied errors.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Add complete CRUD routes for project groups in coordinators.ts:
  - GET /api/project-groups - List all groups with repositories
  - POST /api/project-groups - Create new group
  - PATCH /api/project-groups/:id - Update group
  - DELETE /api/project-groups/:id - Delete group
  - POST /api/project-groups/:id/repositories - Add repos to group
  - DELETE /api/project-groups/:id/repositories/:repoId - Remove repo
  - PUT /api/project-groups/reorder - Reorder groups

- Update CoordinatorPanel.tsx with full CRUD functionality:
  - Display groups with their repositories
  - Create new groups with selected repos
  - Edit group name/description inline
  - Add repos to existing groups
  - Remove repos from groups
  - Delete groups

- Fix App.tsx workspace settings to open full settings page
- Add auth revocation detection to pty-wrapper.ts

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Use 1GB instance for free tier (vs 2GB for paid) to reduce costs (~$7/mo vs ~$15/mo)
- Add compute enforcement cron that checks free tier users every 15 mins and stops workspaces when 5-hour limit exceeded
- Add UsageBanner component showing remaining compute hours with upgrade CTA
- Add admin user system via ADMIN_USERS env var (comma-separated GitHub usernames)
- Admin users bypass Stripe checkout and get enterprise features
- Fix billing page hanging for free tier users without Stripe customer ID
- Add graceful workspace resizing that doesn't disrupt running agents:
  - Stopped workspaces: resize immediately
  - Running workspaces: save config for next restart (skip_launch: true)
- Add workspace resize call after plan upgrade (via Stripe webhook or admin upgrade)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@khaliqgant khaliqgant merged commit 25768c1 into main Jan 6, 2026
6 checks passed
@khaliqgant khaliqgant deleted the architecture-adjustments branch January 6, 2026 19:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants