Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ jobs:
- name: TypeScript type-check
run: pnpm exec tsc --noEmit

- name: Unit tests with coverage
run: pnpm test:coverage

build:
name: Build
runs-on: ubuntu-latest
Expand Down
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,22 @@ Curated list of 2025's best development tools across 17+ categories:
- **Bucket Management**: Save, review, and modify your tool selections
- **Copy & Paste**: One-click script generation and copying

### Architecture

SudoStart uses Hexagonal Architecture for its core workflows:

- `src/domain` contains entities, value objects, repository interfaces, and script-generation domain services.
- `src/application` contains use cases and ports for script generation, AI chat, version fetching, bucket management, and script sharing.
- `src/infrastructure` contains adapters for Groq, future AI providers, package registries, storage, file-backed sharing, and dependency injection.

API routes are kept thin: they handle HTTP validation, rate-limit headers, and response formatting, then delegate to use cases.

More detail:

- [Architecture overview](docs/architecture/hexagonal-overview.md)
- [Developer guide](docs/architecture/developer-guide.md)
- [ADR 0001](docs/adr/0001-hexagonal-architecture.md)

---

## Demo
Expand Down
23 changes: 23 additions & 0 deletions docs/adr/0001-hexagonal-architecture.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ADR 0001: Hexagonal Architecture

## Status

Accepted

## Context

SudoStart needs clearer boundaries between script generation, package/version resolution, AI provider calls, API handlers, and React presentation. The previous structure made Groq, registry HTTP calls, and bucket mutation behavior hard to test or replace independently.

## Decision

Adopt Hexagonal Architecture with three primary layers:

- `src/domain`: pure entities, value objects, repository interfaces, and domain services.
- `src/application`: use cases, DTOs, and incoming/outgoing ports.
- `src/infrastructure`: adapters for AI providers, registries, storage, sharing, and dependency wiring.

Next.js API routes remain in `src/app/api`, but they should only handle HTTP concerns such as request parsing, validation, rate-limit headers, and response formatting. Business workflows are delegated to application use cases.

## Consequences

New AI providers can be added by implementing `AIProvider`. New package/version registries can be added by implementing the repository or registry adapter interfaces. UI and API code should consume use cases rather than depending directly on SDKs, registry helpers, or domain internals.
48 changes: 48 additions & 0 deletions docs/architecture/developer-guide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Developer Guide

## Where New Code Goes

- New business rules belong in `src/domain`.
- New workflows belong in `src/application/use-cases`.
- New external integrations belong in `src/infrastructure/adapters`.
- New UI belongs in `src/presentation/components` with a thin export from `src/components` when preserving existing imports is useful.
- API routes should parse requests, validate HTTP concerns, set headers, and delegate to use cases.

## Package Catalog Access

Do not import `appCatalog` from React components or application use cases. Use the package repository instead:

```ts
import { clientContainer } from '@/infrastructure/config/client-container';

const packages = clientContainer.packageRepository.findForPlatformSync(os);
```

Server-side code should use `container.packageRepository`.

## Version Fetching

UI code should use `FetchVersionsUseCase` through `clientContainer`. Server API routes should use the server `container`.

## AI Action Parsing

AI response parsing and validation belongs to `ParseAIActionUseCase`. React components should only apply the parsed action to UI state.

## Testing

Run:

```bash
pnpm test
pnpm test:coverage
```

Coverage is configured for domain and application layers with an 80% threshold.

## Boundaries Checklist

- No React imports in `domain` or `application`.
- No SDK, `fetch`, filesystem, or browser storage usage in `domain`.
- No direct `appCatalog` imports in components.
- New adapters implement ports or repository interfaces.
- Components call use cases or repositories through browser-safe infrastructure bindings.
64 changes: 64 additions & 0 deletions docs/architecture/hexagonal-overview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Hexagonal Architecture Overview

SudoStart is organized around ports and adapters so core behavior can be tested without React, Next.js, Groq, browser storage, or registry HTTP calls.

## Layers

### Domain

`src/domain` contains the core model:

- Entities: `PackageEntity`, `Script`, `Bucket`
- Value objects: `Platform`, `Shell`, `Version`
- Repository interfaces: `PackageRepository`, `VersionRepository`
- Domain services: script generation and install cost estimation

Domain code should not import React components, API routes, Zustand stores, SDK clients, or browser APIs.

### Application

`src/application` contains use cases and ports:

- `GenerateScriptUseCase`
- `ChatWithAIUseCase`
- `FetchVersionsUseCase`
- `ManageBucketUseCase`
- `ParseAIActionUseCase`
- `ShareScriptUseCase`

Use cases coordinate domain objects and outgoing ports. They should not know whether the caller is a React component, API route, CLI command, or test.

### Infrastructure

`src/infrastructure` contains adapters:

- AI: Groq and future OpenAI adapter
- Catalog: static package repository
- Registries: HTTP and browser version repositories
- Storage: local storage adapter
- Sharing: file-backed script share adapter
- Config: server and browser-safe dependency containers

External dependencies belong here.

### Presentation

`src/presentation` contains UI implementations. `src/components` exposes thin compatibility wrappers so existing imports remain stable while presentation code moves out of the legacy component layer.

Presentation code can call browser-safe use cases through `clientContainer`, but it should not import static catalog data or server adapters directly.

## Dependency Direction

Allowed direction:

`presentation/api -> application -> domain`

Adapters implement ports and are injected from infrastructure containers. Domain and application code do not import infrastructure implementations.

## Adding a Provider or Registry

To add a new AI provider, implement `AIProvider` and wire it in the DI container.

To add a new version source, implement `VersionRepository` or extend the HTTP version repository source map.

To add a new package catalog backend, implement `PackageRepository` and replace the static package repository binding.
149 changes: 149 additions & 0 deletions docs/tickets/github-issue-template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# GitHub Issue Template

Copy and paste the following into a new GitHub issue:

---

## Title
`[ARCHITECTURE] Refactor codebase to Hexagonal Architecture (Ports & Adapters)`

---

## Body

```markdown
## Overview
Refactor the SudoStart codebase from its current layered/component-based architecture to **Hexagonal Architecture** (Ports and Adapters pattern). This will improve testability, maintainability, and make the codebase more extensible for future features.

## Current Problems
- ❌ Business logic (script generation, package resolution) scattered across React components and API routes
- ❌ Tight coupling to Groq AI (hard to swap providers)
- ❌ Tight coupling to specific registries (Homebrew, apt) - Windows support difficult
- ❌ Testing business logic requires mounting React components
- ❌ Adding new features requires changes across multiple layers

## Proposed Solution
Implement Hexagonal Architecture with clear separation:

**Domain Layer (Core)**
- Entities: Package, Script, Bucket
- Value Objects: Version, Platform, Shell
- Domain Services: ScriptGenerator
- Repository Interfaces

**Application Layer**
- Use Cases: GenerateScript, ChatWithAI, FetchVersions, ManageBucket
- DTOs for input/output
- Application Services

**Infrastructure Layer**
- Adapters: GroqAI, Homebrew, Apt, LocalStorage
- API Routes (thin HTTP handlers)
- UI Components (thin presentation layer)

## Implementation Phases

### Phase 1: Domain Layer Foundation [1 day]
- [ ] Create domain entities (Package, Script, Bucket)
- [ ] Create value objects (Version, Platform, Shell)
- [ ] Define repository interfaces
- [ ] Write unit tests (target: 100% coverage)

### Phase 2: Application Layer [1-1.5 days]
- [ ] Implement use cases
- [ ] Create DTOs
- [ ] Write unit tests with mocked repositories

### Phase 3: Infrastructure Adapters [1.5-2 days]
- [ ] Refactor existing registry helpers into adapters
- [ ] Create AI provider abstraction
- [ ] Implement storage adapters
- [ ] Write integration tests

### Phase 4: UI/API Refactoring [1 day]
- [ ] Refactor components to be thin (delegate to use cases)
- [ ] Refactor API routes to be thin HTTP handlers
- [ ] Implement dependency injection
- [ ] Update existing hooks

### Phase 5: Testing & Documentation [0.5-1 day]
- [ ] Achieve >80% test coverage
- [ ] Create architecture documentation
- [ ] Add ADR (Architecture Decision Record)
- [ ] Update README

## Benefits
✅ **Testability**: Unit test business logic without React components
✅ **Flexibility**: Swap AI providers (Groq ↔ OpenAI ↔ Anthropic) with single file change
✅ **Platform Support**: Add Windows (Winget/Chocolatey) by creating new adapter
✅ **Maintainability**: Changes to UI don't affect business logic
✅ **Team Scaling**: Frontend and backend developers work independently

## Success Metrics
- [ ] All existing functionality preserved (feature parity)
- [ ] Unit test coverage > 80% for domain and application layers
- [ ] Component file size < 100 lines (business logic extracted)
- [ ] Zero business logic in UI components
- [ ] New AI provider can be added in < 30 minutes
- [ ] New package registry can be added in < 1 hour

## Risks
| Risk | Mitigation |
|------|------------|
| Breaking changes | Feature branch, comprehensive tests, gradual rollout |
| Increased complexity | Document architecture decisions, team training |
| Time overrun | Break into phases, deliver incrementally |

## Resources
- Detailed ticket: `/docs/tickets/hexagonal-architecture-refactor.md`
- Visual reference: `/docs/tickets/hexagonal-refactor-diagram.md`
- [Hexagonal Architecture by Alistair Cockburn](https://alistair.cockburn.us/hexagonal-architecture/)

## Estimated Effort
**3-5 days** across 5 phases

## Priority
**High** - Blocks Windows support and AI provider flexibility

## Labels
`architecture`, `refactoring`, `technical-debt`, `hexagonal`, `enhancement`
```

---

## Quick Commands to Create Issue

### Option 1: Using GitHub CLI (if installed)
```bash
gh issue create \
--title "[ARCHITECTURE] Refactor codebase to Hexagonal Architecture (Ports & Adapters)" \
--label "architecture,refactoring,technical-debt,enhancement" \
--body-file docs/tickets/github-issue-body.md
```

### Option 2: Using GitHub Web Interface
1. Go to: https://github.com/[username]/sudo-start/issues/new
2. Copy the title above
3. Copy the body above (between the triple backticks)
4. Add labels: `architecture`, `refactoring`, `technical-debt`, `enhancement`
5. Submit issue

---

## Related Files Created

1. **Detailed Ticket**: `docs/tickets/hexagonal-architecture-refactor.md`
- Full implementation plan
- Phase-by-phase breakdown
- Directory structure
- Acceptance criteria

2. **Visual Reference**: `docs/tickets/hexagonal-refactor-diagram.md`
- Before/after architecture diagrams
- Data flow examples
- Testing strategy
- Migration path

3. **This Template**: `docs/tickets/github-issue-template.md`
- Ready-to-use GitHub issue format
```
Loading
Loading