Skip to content
Merged
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
53 changes: 35 additions & 18 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,49 @@ NODE_ENV=development
CORS_ORIGIN=http://localhost:5173

# Database (Neon Postgres)
DATABASE_URL=postgresql://user:password@hostname/dbname?sslmode=require
DATABASE_URL=postgresql://user:password@hostname/dbname?sslmode=require&channel_binding=require

# Authentication (Neon Auth / Better Auth)
# Used to sign sessions. Generate one via: openssl rand -base64 32
BETTER_AUTH_SECRET=your_better_auth_secret_here
# The base URL of your API (needed by Better Auth)
# ── Better Auth (self-hosted, data in Neon Postgres) ───────────────
# See docs/decisions/001-authentication-strategy.md for rationale.
# Generate a fresh 32-byte secret with:
# node -e "console.log(require('crypto').randomBytes(32).toString('base64'))"
# or: openssl rand -base64 32
BETTER_AUTH_SECRET=replace_with_32_byte_base64_secret
BETTER_AUTH_URL=http://localhost:3000
# Local catalog-only development can bypass auth when no DATABASE_URL is set.
# Production always fails closed if auth/database is unavailable.
# Local catalog-only dev may bypass auth when no DATABASE_URL is set.
# Production MUST set this to "false" so auth failures fail closed.
Comment on lines +16 to +17

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Auth bypass comments are inaccurate: bypass applies to all non-production environments unless ALLOW_AUTH_BYPASS=false, not only when DATABASE_URL is missing.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .env.example, line 16:

<comment>Auth bypass comments are inaccurate: bypass applies to all non-production environments unless `ALLOW_AUTH_BYPASS=false`, not only when `DATABASE_URL` is missing.</comment>

<file context>
@@ -4,30 +4,36 @@ NODE_ENV=development
 BETTER_AUTH_URL=http://localhost:3000
-# Local catalog-only development can bypass auth when no DATABASE_URL is set.
-# Production always fails closed if auth/database is unavailable.
+# Local catalog-only dev may bypass auth when no DATABASE_URL is set.
+# Production MUST set this to "false" so auth failures fail closed.
 ALLOW_AUTH_BYPASS=true
</file context>
Suggested change
# Local catalog-only dev may bypass auth when no DATABASE_URL is set.
# Production MUST set this to "false" so auth failures fail closed.
# Local catalog-only dev may bypass auth in non-production when ALLOW_AUTH_BYPASS is not "false".
# Set ALLOW_AUTH_BYPASS=false anywhere you want session auth enforced (including staging).

ALLOW_AUTH_BYPASS=true

# GitHub OAuth (configured in Neon Console for production)
# GitHub OAuth (github.com/settings/developers → New OAuth App)
# Callback URL to register:
# http://localhost:3000/api/auth/callback/github (local)
# https://<api-domain>/api/auth/callback/github (production)
GITHUB_CLIENT_ID=your_github_client_id
GITHUB_CLIENT_SECRET=your_github_client_secret

# Admin API Key (For protecting /admin and /internal routes)
# Admin API Key (protects /admin and /internal routes)
ADMIN_API_KEY=your_admin_api_key_here

# AI Provider (controls which LLM powers blueprint explanations)
# Options: gemini | openai | heuristic (heuristic = no API key needed)
AI_PROVIDER=gemini
AI_MODEL=gemini-2.0-flash # Optional: override the default model
AI_MAX_TOKENS=2048 # Max tokens per AI response
AI_TIMEOUT_MS=30000 # Timeout in ms before falling back to heuristic
# ── AI Provider (controls which LLM powers blueprint explanations)
# Supported in packages/ai today: heuristic | gemini | azure-openai
AI_PROVIDER=heuristic
# Generic tuning (applies to whichever provider is active)
AI_MAX_TOKENS=2048
AI_TIMEOUT_MS=30000

# API Keys — only the key for your chosen AI_PROVIDER is required
# Gemini (Google Generative AI) — used when AI_PROVIDER=gemini
GEMINI_API_KEY=your_gemini_api_key
OPENAI_API_KEY=sk-your_openai_api_key
ANTHROPIC_API_KEY=sk-ant-your_anthropic_api_key
# Optional model override for Gemini. Defaults to gemini-2.5-flash.
AI_MODEL=gemini-2.5-flash

# Azure OpenAI — used when AI_PROVIDER=azure-openai
# Create a deployment in Azure AI Foundry (gpt-5.5 or gpt-4.1, for example),
# then set the resource sub-domain and deployment name below.
AZURE_OPENAI_RESOURCE_NAME=your_resource_name
AZURE_OPENAI_API_KEY=your_azure_openai_api_key
AZURE_OPENAI_DEPLOYMENT=gpt-5.5
# Optional API version pin. Leave unset to use the SDK default.
AZURE_OPENAI_API_VERSION=
# Legacy OpenAI key is unused for Stackfast's Azure-only setup but
# is kept for operators who swap in the standard OpenAI endpoint.
OPENAI_API_KEY=
11 changes: 9 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,15 @@ jobs:
version: 9

- name: Get pnpm store directory
id: pnpm-store
shell: bash
run: |
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
echo "path=$(pnpm store path --silent)" >> $GITHUB_OUTPUT

- name: Setup pnpm cache
uses: actions/cache@v4
with:
path: ${{ env.STORE_PATH }}
path: ${{ steps.pnpm-store.outputs.path }}
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
${{ runner.os }}-pnpm-store-
Expand All @@ -53,3 +54,9 @@ jobs:

- name: Validate Registry
run: pnpm validate:registry

- name: Install Playwright browsers
run: pnpm exec playwright install --with-deps chromium

- name: E2E Tests
run: pnpm test:e2e
10 changes: 5 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,8 @@ web_modules/

# dotenv environment variables file
.env
.env.test
.env.production
.env.local
.env.*.local
.env.*
!.env.example

# parcel-bundler cache (https://parceljs.org/)
.cache
Expand Down Expand Up @@ -138,4 +136,6 @@ Thumbs.db
# Project specific
server/public/
vite.config.ts.*
.local/
.local/
test-results/
playwright-report/
1 change: 0 additions & 1 deletion Branches/StackFast-101
Submodule StackFast-101 deleted from a2ff20
1 change: 0 additions & 1 deletion Branches/StackWiseAI/StackWiseAI
Submodule StackWiseAI deleted from 529cf6
1 change: 0 additions & 1 deletion Branches/StackfastPro
Submodule StackfastPro deleted from 92046a
21 changes: 0 additions & 21 deletions Dockerfile

This file was deleted.

39 changes: 23 additions & 16 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@ Secure existing work and remove dead weight before building anything new.
### Deliverables
- [x] Archive branch `archive/pre-rebuild` created
- [x] Salvage manifest finalized (SALVAGE_MANIFEST.md)
- [ ] Old branches deleted (StackFastold, StackFast1)
- [ ] developer-tools-api deleted
- [ ] Stale docs deleted (5 files)
- [x] Old branches deleted (StackFastold, StackFast1, StackfastPro, StackFast-101, StackWiseAI)
- [x] developer-tools-api deleted
- [x] Stale docs deleted (5 files) — 3 actual deletions + 2 moved to `docs/backlog/` and `docs/deferred/`
- [x] `.env` files removed from source
- [x] `desktop.ini` files removed recursively
- [x] `.gitignore` updated with comprehensive exclusions
- [ ] Clean commit: "Phase 0: Repository cleanup for 2026 rebuild"
- [x] Post-extraction cleanup complete (root `client/`, `server/`, `shared/`, `Branches/`, `Referencedocs/`, legacy build configs, logs, debris)
- [x] Clean commit: "Phase 0: Repository cleanup for 2026 rebuild"

### Risk
**Low.** Archive branch preserves everything. Reversible.
Expand Down Expand Up @@ -154,7 +155,7 @@ Ship a polished frontend that makes the API accessible and delightful.
Make the blueprint generator actually valuable with LLM-powered explanations.

### Deliverables
- [ ] `packages/ai/` — Provider abstraction (OpenAI/Gemini/Anthropic)
- [x] `packages/ai/` — Provider abstraction (heuristic, Gemini, Azure OpenAI)
- [x] Deterministic rules remain source of truth for scoring
- [x] LLM adds explanation and synthesis layer
- [x] Every AI response validated with Zod
Expand All @@ -166,7 +167,13 @@ Make the blueprint generator actually valuable with LLM-powered explanations.
- [x] Fallback to deterministic-only mode if AI unavailable

### Current Status
**Started/in progress.** Gemini-backed explanation and deterministic fallback paths exist, but the provider abstraction is incomplete and OpenAI/Anthropic support remains stubbed or not implemented.
**Phase 5 scope is complete for MVP.** `heuristic`, `gemini`, and
`azure-openai` providers ship in `packages/ai`. The operator's Azure AI
Foundry resource (with `gpt-5.5` / `gpt-4.1` deployments) is the primary
production provider; Gemini remains available as a lower-cost fallback.
Every AI call is wrapped in a heuristic fallback and validated with Zod.
See `docs/decisions/002-ai-provider-strategy.md`. The one remaining item
(ADR generation in the blueprint response itself) is deferred to v1.1.

### Risk
**Medium.** LLM integration introduces latency and cost. Provider API changes can break things. Zod validation of AI output needs thorough testing.
Expand Down Expand Up @@ -223,13 +230,13 @@ Build a registry that's genuinely useful for 2026 technology decisions.
- [x] Zero type errors across all packages
- [x] All unit tests pass (rules, scoring, registry, exporter, schemas)
- [x] API contract tests for every public endpoint
- [ ] Playwright E2E tests for primary flows
- [x] Playwright E2E tests for primary flows
- [x] Security tests for admin routes and rate limiting
- [x] CI pipeline blocks merge on any failure
- [x] Small seed dataset for database-free local dev

### Current Status
**Basic quality gate is green.** Lint, type-check, unit tests, builds, registry validation, API contract coverage, admin protection checks, and rate-limit tests pass. E2E and deeper security testing remain open.
**Quality gate is green for the MVP codebase.** Type-check, lint, unit/API tests, builds, registry validation, API contract coverage, admin protection checks, rate-limit tests, and Playwright E2E MVP flows pass locally. Remaining security/deployment hardening belongs to Phase 8.

---

Expand All @@ -254,14 +261,14 @@ Build a registry that's genuinely useful for 2026 technology decisions.

| Feature | Status | Priority |
|---------|--------|----------|
| Idea-to-stack blueprint | 🔲 | P0 |
| Compatibility-scored stack options | 🔲 | P0 |
| Tool search and details | 🔲 | P0 |
| Stack builder with diagnostics | 🔲 | P0 |
| Starter file export | 🔲 | P0 |
| Alternatives and tradeoffs | 🔲 | P0 |
| GitHub OAuth login | 🔲 | P0 |
| Migration path (basic) | 🔲 | P1 |
| Idea-to-stack blueprint | | P0 |
| Compatibility-scored stack options | | P0 |
| Tool search and details | | P0 |
| Stack builder with diagnostics | | P0 |
| Starter file export | | P0 |
| Alternatives and tradeoffs | | P0 |
| GitHub OAuth login | ⚠️ Configured, production verification pending | P0 |
| Migration path (basic) | | P1 |

### NOT in MVP

Expand Down
54 changes: 0 additions & 54 deletions Referencedocs/README_CI_DOCKER.md

This file was deleted.

42 changes: 42 additions & 0 deletions SALVAGE_MANIFEST.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,48 @@

## Post-Extraction Cleanup

Completed on 2026-05-11. The following were removed from the main working tree
(all preserved on `origin/archive/pre-rebuild` if ever needed):

1. Root `client/` (old React app — 104 files)
2. Root `server/` (old Express/Drizzle server — 19 files)
3. Root `shared/schema.ts` (migrated to `packages/schemas/src/db.ts`)
4. `Branches/StackFast-101/`, `Branches/StackfastPro/` (orphan submodule
gitlinks — no `.gitmodules` ever existed, so git couldn't hydrate them)
5. `Branches/StackWiseAI/` (inspiration-only, concepts already documented)
6. `WebAILyzerAPI/` (orphan submodule gitlink; SHA preserved in
`docs/deferred/webailyzer.md` for post-MVP revival)
7. `Referencedocs/` — `INTEGRATION_PLAN.md` moved to `docs/backlog/`,
`README_CI_DOCKER.md` dropped (superseded by current CI workflow)
8. Root build configs: `vite.config.ts`, `tailwind.config.ts`, `tsconfig.json`,
`postcss.config.js`, `drizzle.config.ts`, `components.json` (each app now
owns its own config)
9. Root `Dockerfile` (npm-based, port 5000 — will be rewritten for monorepo
deployment in Phase 8)
10. Root `package-lock.json` (monorepo uses `pnpm-lock.yaml`)
11. `attached_assets/` (legacy screenshots and docs — 23 files, 5.8MB)
12. `fix-scores.js`, `export.csv`, `dev.log`, `run.log` (stale debris)

The repository now contains only:
```
stackfast/
├── apps/web/
├── apps/api/
├── packages/{registry,rules-engine,schemas,exporter,ai,shared}/
├── docs/{decisions,backlog,deferred}/
├── tests/e2e/
├── scripts/
├── .github/workflows/
├── pnpm-workspace.yaml
├── tsconfig.base.json
├── .env.example
├── .gitignore
├── Agents.md
├── readme.md
├── ROADMAP.md
└── SALVAGE_MANIFEST.md
```

After all files are extracted to their new locations:

1. Delete `Branches/StackFast-101/` (no longer needed as reference)
Expand Down
1 change: 0 additions & 1 deletion WebAILyzerAPI
Submodule WebAILyzerAPI deleted from c4b2b8
28 changes: 14 additions & 14 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,31 @@
"private": true,
"type": "module",
"scripts": {
"dev": "tsx watch src/index.ts",
"dev": "dotenv -e ../../.env -- tsx watch src/index.ts",
"build": "tsc",
"start": "node dist/index.js",
"start": "dotenv -e ../../.env -- node dist/index.js",
"lint": "eslint src/",
"type-check": "tsc --noEmit",
"test": "vitest run --config ../../vitest.package.config.ts",
"seed": "tsx src/db/seed.ts"
"test": "vitest run",
"seed": "dotenv -e ../../.env -- tsx src/db/seed.ts"
},
"dependencies": {
"@stackfast/shared": "workspace:*",
"@stackfast/schemas": "workspace:*",
"@hono/node-server": "^1.13.7",
"@neondatabase/serverless": "^0.10.4",
"@stackfast/ai": "workspace:*",
"@stackfast/exporter": "workspace:*",
"@stackfast/registry": "workspace:*",
"@stackfast/rules-engine": "workspace:*",
"@stackfast/exporter": "workspace:*",
"@stackfast/ai": "workspace:*",
"hono": "^4.6.1",
"@hono/node-server": "^1.13.7",
"@stackfast/schemas": "workspace:*",
"@stackfast/shared": "workspace:*",
"better-auth": "^1.1.13",
"zod": "^3.24.2",
"drizzle-orm": "^0.45.2",
"@neondatabase/serverless": "^0.10.4"
"hono": "^4.6.1",
"zod": "^3.24.2"
},
"devDependencies": {
"typescript": "^5.6.3",
"@types/node": "^22.10.2",
"tsx": "^4.19.2",
"@types/node": "^22.10.2"
"typescript": "^5.6.3"
}
}
Loading
Loading