|
| 1 | +# PROJECT KNOWLEDGE BASE |
| 2 | + |
| 3 | +**Generated:** 2026-02-12 |
| 4 | +**Commit:** e66675e |
| 5 | +**Branch:** main |
| 6 | + |
| 7 | +## OVERVIEW |
| 8 | + |
| 9 | +Web dashboard and install API for OpenBoot. SvelteKit 5 + Cloudflare Workers + D1 (SQLite). |
| 10 | +Serves config pages, install scripts (curl|bash), dashboard UI, OAuth login, and docs. |
| 11 | + |
| 12 | +## STRUCTURE |
| 13 | + |
| 14 | +``` |
| 15 | +openboot.dev/ |
| 16 | +├── src/ |
| 17 | +│ ├── app.d.ts # Platform env types (DB, secrets) |
| 18 | +│ ├── app.html # HTML shell |
| 19 | +│ ├── hooks.server.ts # Request interceptor: alias resolution, curl detection, security headers |
| 20 | +│ ├── docs/ # Markdown docs (mdsvex), 12 pages |
| 21 | +│ ├── lib/ |
| 22 | +│ │ ├── components/ # ThemeToggle, Button, SearchModal |
| 23 | +│ │ ├── server/ # auth.ts, install-script.ts, rate-limit.ts, validation.ts |
| 24 | +│ │ ├── stores/ # auth.ts, theme.ts (Svelte stores) |
| 25 | +│ │ └── presets.ts # Preset package definitions |
| 26 | +│ └── routes/ |
| 27 | +│ ├── +page.svelte # Landing page |
| 28 | +│ ├── dashboard/ # Authenticated config management UI |
| 29 | +│ ├── login/ # OAuth login page |
| 30 | +│ ├── cli-auth/ # CLI OAuth approval flow |
| 31 | +│ ├── docs/ # Docs layout + per-page routing |
| 32 | +│ ├── install/ # /install.sh redirect |
| 33 | +│ ├── [username]/[slug]/ # Config page, install endpoint, config JSON, OG image |
| 34 | +│ └── api/ |
| 35 | +│ ├── auth/ # OAuth callbacks (GitHub, Google), CLI auth (start/poll/approve), logout |
| 36 | +│ ├── configs/ # CRUD: GET/POST list, [slug] GET/PUT/DELETE, from-snapshot |
| 37 | +│ ├── user/ # Current user info |
| 38 | +│ ├── homebrew/search/ # Homebrew package search proxy |
| 39 | +│ ├── npm/search/ # NPM package search proxy |
| 40 | +│ └── brewfile/parse/ # Brewfile import parser |
| 41 | +├── migrations/ # D1 SQL migrations (0001-0006) |
| 42 | +├── wrangler.toml # Cloudflare Workers config, D1 binding |
| 43 | +└── .github/workflows/deploy.yml # CI/CD |
| 44 | +``` |
| 45 | + |
| 46 | +## WHERE TO LOOK |
| 47 | + |
| 48 | +| Task | Location | Notes | |
| 49 | +|------|----------|-------| |
| 50 | +| Add API endpoint | `src/routes/api/` | SvelteKit `+server.ts` convention | |
| 51 | +| Change install script | `src/lib/server/install-script.ts` | Shell script template generator | |
| 52 | +| Update auth logic | `src/lib/server/auth.ts` | JWT verify, getCurrentUser, slugify, generateId | |
| 53 | +| Add validation rules | `src/lib/server/validation.ts` | Custom script + dotfiles repo validation | |
| 54 | +| Change rate limits | `src/lib/server/rate-limit.ts` | In-memory rate limiter | |
| 55 | +| Edit curl/alias routing | `src/hooks.server.ts` | Alias → config lookup, user-agent detection | |
| 56 | +| Change config visibility | `src/routes/api/configs/` + server routes | `visibility` field: public/unlisted/private | |
| 57 | +| Add docs page | `src/docs/` | Markdown with frontmatter (title, group, order) | |
| 58 | +| Add DB column | `migrations/` | Sequential `0007_*.sql`, auto-applied by CI | |
| 59 | +| Change presets | `src/lib/presets.ts` | Package lists for minimal/developer/full | |
| 60 | +| Modify landing page | `src/routes/+page.svelte` | Single-file component | |
| 61 | +| Update dashboard | `src/routes/dashboard/+page.svelte` | Config CRUD UI | |
| 62 | + |
| 63 | +## DB SCHEMA |
| 64 | + |
| 65 | +D1 (SQLite). Key table: |
| 66 | + |
| 67 | +```sql |
| 68 | +configs ( |
| 69 | + id TEXT PRIMARY KEY, |
| 70 | + user_id TEXT, |
| 71 | + slug TEXT, |
| 72 | + name TEXT, |
| 73 | + description TEXT, |
| 74 | + base_preset TEXT, |
| 75 | + packages TEXT, -- JSON array of {name, type, desc} |
| 76 | + custom_script TEXT, |
| 77 | + dotfiles_repo TEXT, |
| 78 | + snapshot TEXT, -- JSON object from CLI snapshot |
| 79 | + alias TEXT UNIQUE, |
| 80 | + visibility TEXT DEFAULT 'unlisted', -- 'public' | 'unlisted' | 'private' |
| 81 | + install_count INTEGER DEFAULT 0, |
| 82 | + created_at TEXT, |
| 83 | + updated_at TEXT |
| 84 | +) |
| 85 | +``` |
| 86 | + |
| 87 | +Visibility rules: |
| 88 | +- **public**: listed on profile, install URL works, config page viewable |
| 89 | +- **unlisted**: NOT listed, install URL works, config page viewable |
| 90 | +- **private**: owner-only, install URL returns 403 |
| 91 | + |
| 92 | +## REQUEST FLOW |
| 93 | + |
| 94 | +``` |
| 95 | +curl openboot.dev/alias → hooks.server.ts → alias lookup → install script |
| 96 | +curl openboot.dev/user/slug → hooks.server.ts → two-segment curl detection → install script |
| 97 | +browser openboot.dev/alias → hooks.server.ts → redirect to /user/slug |
| 98 | +browser openboot.dev/user/slug → [username]/[slug]/+page.server.ts → config page |
| 99 | +``` |
| 100 | + |
| 101 | +## CONVENTIONS |
| 102 | + |
| 103 | +- **Auth**: JWT in httpOnly cookie (`openboot_token`). `getCurrentUser()` from `$lib/server/auth` |
| 104 | +- **API responses**: Always `json({...})` with appropriate status codes |
| 105 | +- **Rate limiting**: In-memory, per user ID. CONFIG_READ and CONFIG_WRITE limits |
| 106 | +- **Input validation**: Server-side in route handlers. Visibility must be `public|unlisted|private` |
| 107 | +- **Security headers**: Applied globally in `hooks.server.ts` (CSP, HSTS, X-Frame-Options) |
| 108 | +- **Slug generation**: `slugify()` from `$lib/server/auth` — lowercase, alphanumeric + hyphens |
| 109 | +- **Error handling**: Return `json({ error: '...' }, { status: N })`, never throw in API routes |
| 110 | +- **Svelte 5**: Uses `$state`, `$derived`, `$props()` runes (not legacy `$:` reactive) |
| 111 | + |
| 112 | +## ANTI-PATTERNS |
| 113 | + |
| 114 | +- No `as any` or `@ts-ignore` — type properly |
| 115 | +- No direct DB access outside `+server.ts` files — always through API routes |
| 116 | +- No client-side secrets — all OAuth secrets in platform env |
| 117 | +- No raw SQL without parameterized bindings — always `.bind()` |
| 118 | +- No `is_public` — replaced by `visibility` field (migration 0006) |
| 119 | + |
| 120 | +## COMMANDS |
| 121 | + |
| 122 | +```bash |
| 123 | +npm run dev # Local dev server |
| 124 | +npm run build # Production build |
| 125 | +npm run preview # Preview production build |
| 126 | +npm run check # Type checking |
| 127 | +npx wrangler d1 migrations apply openboot --local # Apply migrations locally |
| 128 | +npx wrangler d1 migrations apply openboot --remote # Apply migrations to prod |
| 129 | +npx wrangler dev # Dev with D1 binding |
| 130 | +``` |
| 131 | + |
| 132 | +## CI/CD |
| 133 | + |
| 134 | +Push-to-main auto-deploy via `.github/workflows/deploy.yml`: |
| 135 | + |
| 136 | +1. `npm install` → `npm run build` |
| 137 | +2. `wrangler d1 migrations apply openboot --remote` (runs pending migrations) |
| 138 | +3. `wrangler deploy` (via cloudflare/wrangler-action) |
| 139 | + |
| 140 | +Migrations run **before** deploy — safe for schema changes that new code depends on. |
| 141 | + |
| 142 | +## NOTES |
| 143 | + |
| 144 | +- **Cloudflare D1**: SQLite-compatible. No ALTER TABLE DROP COLUMN. Plan column removals carefully. |
| 145 | +- **OG images**: Generated server-side with `@cf-wasm/resvg` SVG→PNG at `[username]/[slug]/og` |
| 146 | +- **Docs**: Markdown in `src/docs/`, preprocessed by mdsvex, syntax highlighted by shiki. |
| 147 | +- **CLI integration**: CLI calls `/api/configs/from-snapshot` to upload snapshots. Only reads `slug` from response. |
| 148 | +- **OAuth**: GitHub + Google. Callbacks at `/api/auth/callback/{github,google}`. |
| 149 | +- **CLI auth**: Polling flow — CLI calls `/api/auth/cli/start`, user approves at `/cli-auth`, CLI polls `/api/auth/cli/poll`. |
0 commit comments