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
8 changes: 4 additions & 4 deletions .cursor/rules/CODE_STYLE.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@ yarn lint

### Automated Formatting

Code is automatically formatted on commit via Husky:
Code is automatically formatted on commit via Husky and lint-staged:

```json
{
"lint-staged": {
"*.{ts,tsx}": ["eslint --fix", "prettier --write", "git add"]
}
"lint-staged": {
"*.{ts,tsx}": ["eslint --cache --fix", "prettier --write"]
}
}
```

Expand Down
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DATABASE_URL=postgres://stackcraft:stackcraft@localhost:5433/stackcraft
18 changes: 18 additions & 0 deletions .github/workflows/ui-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ jobs:
matrix:
node-version: [22.x, 24.x]

services:
postgres:
image: postgres:17-alpine
env:
POSTGRES_USER: stackcraft
POSTGRES_PASSWORD: stackcraft
POSTGRES_DB: stackcraft
ports:
- 5433:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5

env:
DATABASE_URL: postgres://stackcraft:stackcraft@localhost:5433/stackcraft

steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
Expand Down
1 change: 0 additions & 1 deletion .husky/.gitignore

This file was deleted.

1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
52 changes: 52 additions & 0 deletions .yarn/changelogs/common.6a9239ac.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!-- version-type: minor -->
# common

## ✨ Features

### Domain Model Layer

Added a full domain model layer for stack and service management, replacing the previous minimal `User`-only model surface:

- `StackDefinition` / `StackConfig` — stack metadata, main directory, and environment variable configuration
- `ServiceDefinition` / `ServiceConfig` — service commands, working directory, file definitions, and prerequisite associations
- `ServiceStatus` — typed status per pipeline stage (`CloneStatus`, `InstallStatus`, `BuildStatus`, `RunStatus`)
- `ServiceGitStatus` — branch name, commits behind remote, and auto-fetch flag
- `ServiceStateHistory` / `ServiceStateEvent` — audit trail of state transitions with trigger source tracking
- `ServiceLogEntry` — structured log entries per service process
- `GitHubRepository` — linked Git repository with URL and branch configuration
- `Prerequisite` / `PrerequisiteCheckResult` — typed prerequisites (Node.js, Yarn, .NET, NuGet, env var, custom script) with check status
- `ApiToken` / `PublicApiToken` — bearer token management for REST and MCP authentication
- `EnvironmentVariableValue` — environment variables with `isSecret` flag for encryption support
- `StackView` / `ServiceView` — entity views for filtered data projection

### Typed REST API Definitions

Replaced the single monolithic `StackCraftApi` with individual typed API interfaces, each with its own generated JSON schema:

- `IdentityApi` — authentication, current user, login/logout, password reset
- `InstallApi` — first-run service status and installation trigger
- `StacksApi` — stack CRUD, import/export, and setup orchestration
- `ServicesApi` — service CRUD, lifecycle actions (start/stop/restart/install/build/pull/setup/update), logs, history, branches, checkout, and file application
- `GitHubRepositoriesApi` — repository CRUD with URL validation
- `PrerequisitesApi` — prerequisite CRUD with on-demand check execution
- `TokensApi` — API token creation, listing, and deletion
- `SystemApi` — environment variable availability checks

### Service Path Utilities

- Added `getRepoNameFromUrl()` to extract repository names from Git URLs
- Added `getServiceCwd()` to resolve a service's working directory from stack config, service definition, and repository URL

## ♻️ Refactoring

- Removed `StackCraftApi` and `BoilerplateApi` single-API types in favor of per-domain API modules
- Removed test-only endpoints (`TestQueryEndpoint`, `TestUrlParamsEndpoint`, `TestPostBodyEndpoint`)
- Schema generation now emits one JSON file per API module instead of a single `stack-craft-api.json`

## 🧪 Tests

- Added unit tests for `getRepoNameFromUrl()` and `getServiceCwd()` path utilities

## ⬆️ Dependencies

- Added `@furystack/core` for shared entity types (`WithOptionalId`)
90 changes: 90 additions & 0 deletions .yarn/changelogs/frontend.6a9239ac.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<!-- version-type: minor -->
# frontend

## ✨ Features

### Nested Routing System

Implemented a full nested routing system with typed navigation helpers (`StackCraftNestedRouteLink`, `stackCraftNavigate`) and URL-driven breadcrumb navigation. All routes are scoped under stacks for contextual navigation.

### Dashboard

Stack overview page displaying all stacks with entity-sync–powered live updates. Selecting a stack shows its services, status, and quick actions.

### Service Management

- **Services list** with pipeline status indicators (clone → install → build → run) and bulk actions
- **Service detail page** with pipeline stepper, log viewer, branch selector, environment overrides, prerequisite status, and lifecycle controls (start/stop/restart/install/build/pull/setup/update)
- **Service logs** with ANSI color rendering, per-process filtering, and log clearing
- **Create service wizard** with two-step flow: define service then optional automated setup

### Stack Management

- **Create/edit stack** with name, display name, main directory, and markdown description
- **Stack import/export** for portability between environments with environment variable remapping
- **Stack setup** progress page showing clone/install/build readiness per service

### Repository Management

- **Repository list/create/edit** pages for managing linked GitHub repositories with URL validation

### Prerequisites Management

- **Prerequisites list** with check status display and typed creation form supporting Node.js, Yarn, .NET SDK, NuGet feeds, environment variables, and custom scripts

### User Settings

- Theme selection with persistent storage
- Password change form
- API token management (create, list, delete)

### Installer Wizard

Full-screen first-run wizard with prerequisite checks, admin user creation, and success confirmation — shown automatically when the backend reports an uninstalled state.

### Layout and Navigation

- **Sidebar** with collapsible per-stack navigation sections (services, repositories, prerequisites, import/export)
- **Header** with breadcrumbs, theme toggle, and logout
- **Entity sync** via WebSocket (`/api/ws`) for real-time collection updates across all views

### UI Components

- `ServicePipelineStepper` / `MiniPipelineDots` — visualize clone/install/build/run stages with color-coded status
- `BranchSelector` — Git branch switching with remote branch listing
- `EnvironmentVariablesManager` — stack-level env var editing with secret masking and availability checks
- `ServiceEnvOverrides` — per-service environment variable override editing
- `LogViewer` / `LogLine` — streaming log display with ANSI escape sequence rendering
- `PrerequisiteTable` / `PrerequisiteList` — prerequisite display with check status chips
- `ServiceTable` / `RepositoryTable` — data tables with status indicators and actions
- `StatusChips` — colored status badges for pipeline stages and prerequisite types

### Utilities

- `parseAnsi()` — parses ANSI escape sequences into styled segments for terminal log rendering
- `getServicePipelineStages()` / `getServicePrimaryAction()` — derive pipeline visualization data and contextual actions from service state
- `applyClientFindOptions()` — client-side `FindOptions` filtering, ordering, and pagination

### Per-API REST Clients

Replaced monolithic `StackCraftApiClient` with individual typed clients: `IdentityApiClient`, `StacksApiClient`, `ServicesApiClient`, `GitHubReposApiClient`, `PrerequisitesApiClient`, `TokensApiClient`, `SystemApiClient`, `InstallApiClient`.

## ♻️ Refactoring

- Restructured app shell into `Header` + `Sidebar` + `Body` layout with auth/install gating
- Replaced `StackCraftApiClient` and `BoilerplateApiClient` with per-domain API clients
- Session service now uses `IdentityApiClient` with full `User` type and `[Symbol.dispose]` cleanup

## 🧪 Tests

- Added unit tests for ANSI escape sequence parser (`parse-ansi.spec.ts`)
- Added unit tests for service pipeline stage derivation and action mapping (`service-pipeline.spec.ts`)

## 📦 Build

- Migrated to Vite 8 with synchronous `defineConfig`

## ⬆️ Dependencies

- Added `@furystack/cache`, `@furystack/entity-sync`, `@furystack/entity-sync-client` for live data sync
- Bumped Vite to v8, Vitest to v4
91 changes: 91 additions & 0 deletions .yarn/changelogs/service.6a9239ac.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!-- version-type: minor -->
# service

## ✨ Features

### Process Manager

Added `ProcessManager` to orchestrate service lifecycle (clone, install, build, run, pull, setup, update) with child process management, `ServiceStateHistory` audit trail, and batched log forwarding to `LogStorageService`. Automatically reconciles stale states on startup.

### Git Integration

- `GitService` — wrapper for git operations: clone, fetch, pull, list branches, current branch, commits behind remote, and checkout
- `GitWatcher` — periodic remote fetch (default 5 min) per service with auto-fetch toggle; updates `ServiceGitStatus` and service status when remotes change
- `GitHeadWatcher` — monitors `.git/HEAD` for branch switches and updates branch/behind counts in `ServiceGitStatus`

### MCP Server

Exposed a Model Context Protocol server (Streamable HTTP on port 9091) with bearer token authentication and tools for:

- `stack-tools` — list, get, create, update, delete, export, import, and setup stacks
- `service-tools` — list, create, edit, delete services; start/stop/restart/install/build/pull/setup/update lifecycle; get logs and state history
- `prerequisite-tools` — list, check, create, update, and delete prerequisites
- `repository-tools` — list, get, create, update, delete, and validate repositories
- `env-variable-tools` — set/remove stack env variables and service env overrides
- `service-file-tools` — manage shared and local encrypted service files (list/read/add/update/remove/apply)
- `system-tools` — check environment variable availability

### Security

- `CryptoService` with AES-256-GCM encryption for sensitive environment variables and service files, keyed from `STACK_CRAFT_ENCRYPTION_KEY` or auto-generated `~/.stack-craft/encryption.key`
- `SecretDetector` with heuristic scanning for secrets in commands and file content
- Bearer API token authentication (`BearerTokenAuth`) with SHA-256 hashed storage; plaintext returned only at creation time
- Sensitive data masking on REST responses for environment variables and service files
- Startup migration (`encryptExistingSecrets`) to encrypt pre-existing plaintext secrets in the database

### Prerequisite Evaluation

Prerequisite check system supporting Node.js version, Yarn version, .NET SDK version, NuGet feed availability, environment variable presence, and custom script execution. Evaluates all prerequisites in the background after startup.

### Stack Import/Export

- `exportStackAction` — serializes a stack with its services, repositories, and prerequisites to JSON
- `importStackAction` — imports a stack from JSON with environment variable remapping, deduplication, and conflict resolution

### WebSocket Entity Sync

Real-time entity synchronization via WebSocket at `/api/ws` using `SyncSubscribeAction` / `SyncUnsubscribeAction` for live frontend updates.

### Additional REST Endpoints

- Password reset flow via `/api/identity/password-reset`
- `LogStorageService` for per-service log persistence, query, and pruning
- Repository URL validation via `git ls-remote`
- Environment variable availability check at `/api/system/check-env-availability`
- Service file application to disk via `/api/services/:id/apply-files`

## ♻️ Refactoring

### PostgreSQL Migration

Migrated from `@furystack/filesystem-store` (file-backed JSON) to PostgreSQL via `@furystack/sequelize-store` with Sequelize models and JSONB columns for flexible fields. In-memory stores retained for transient data (`ServiceGitStatus`, `PrerequisiteCheckResult`, sessions, log entries).

### REST API Reorganization

Restructured the REST API into domain-specific modules: identity, install, stacks, services, github-repositories, prerequisites, tokens, and system — each with dedicated setup, actions, and authorization.

### Seed Removal

Replaced the `seed.ts` script with an installer flow triggered from the frontend on first run.

## 🧪 Tests

- `ProcessManager` — lifecycle orchestration, state transitions, log batching, stale state reconciliation
- `GitService` — clone, fetch, pull, branches, current branch, commits behind, checkout
- `CryptoService` — encrypt/decrypt round-trip, key generation, tamper detection
- `env-encryption-helpers` — encrypt/mask/decrypt for stack and service payloads, `UNCHANGED_SENTINEL` handling
- `secret-detector` — heuristic pattern matching for secrets in commands and file content
- `apply-service-files` — merge and write service file definitions to disk
- `check-prerequisite-action` — all prerequisite types and edge cases
- `service-branches-action` / `service-checkout-action` — branch listing and checkout flows
- `service-lifecycle-action` — lifecycle action dispatching
- `import-export-actions` — stack export/import with remapping and deduplication
- `setup-tokens-rest-api` — token CRUD with hashed storage
- `bearer-token-auth` — token resolution and user loading
- `service-installer` — installation flow
- `config` / `get-cors-options` / `get-port` — configuration resolution

## ⬆️ Dependencies

- Added `sequelize`, `pg`, `pg-hstore`, `@furystack/sequelize-store` for PostgreSQL support
- Removed `@furystack/filesystem-store`
34 changes: 34 additions & 0 deletions .yarn/changelogs/stack-craft.6a9239ac.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<!-- version-type: minor -->
# stack-craft

## ✨ Features

- Added PostgreSQL via `docker-compose.yml` for local development (port 5433, `postgres:17-alpine`)
- Added `.env.example` with `DATABASE_URL` configuration for quick setup
- Added separate E2E test suites: installer flow (`test:e2e:install`), smoke tests (`smoke.spec.ts`), and dogfooding tests (`dogfooding.spec.ts`) covering real repository clone/install/build/run

## ♻️ Refactoring

- Renamed `test:unit` script to `test` for simplicity
- Split E2E tests into focused scenarios (installer, smoke, dogfooding) replacing the single `page.spec.ts`

## 👷 CI

- Added PostgreSQL service container to the `ui-tests` workflow with health checks
- Separated installer E2E (`test:e2e:install`) from app E2E in the CI pipeline
- Moved heavy Playwright tests from `build-test` to `ui-tests` workflow to keep the default build fast

## 📚 Documentation

- Updated README with PostgreSQL setup instructions, Docker run example with `DATABASE_URL`, and revised testing commands

## 📦 Build

- Upgraded to Yarn 4.13.0
- Upgraded ESLint to v10 with `@furystack/eslint-plugin` (replacing `eslint-plugin-playwright`)
- Upgraded Vite to v8, Vitest to v4, `@playwright/test` to v1.58

## ⬆️ Dependencies

- Added `jsdom` for Vitest browser environment
- Bumped `typescript-eslint`, `lint-staged`, `rimraf`, `@types/node`
5 changes: 5 additions & 0 deletions .yarn/versions/6a9239ac.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
releases:
common: minor
frontend: minor
service: minor
stack-craft: minor
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,19 @@ Example web app with common type API definitions, a FuryStack-based backend serv

1. Clone the repository
1. Install the dependencies with `yarn`
1. Start PostgreSQL (e.g. `docker compose up -d`)
1. Copy `.env.example` to `.env` and adjust if needed
1. Start the frontend and the backend service with `yarn start` (you can stop / start them individually, check the NPM scripts for further details)

## Docker

When running the Docker image, pass the `DATABASE_URL` environment variable:

```bash
docker run -e DATABASE_URL=postgres://user:password@host:5433/stackcraft furystack/stack-craft
```

# Testing

- You can execute the example Vitest tests with `yarn test`
- You can execute E2E tests with `yarn test:e2e`
- You can execute E2E tests with `yarn test:e2e` (requires a running PostgreSQL instance and `DATABASE_URL` set)
Loading
Loading