go get bumped go.mod to 'go 1.25.0' (modernc requirement), but CI used setup-go
1.24 and the image used golang:1.24 — with GOTOOLCHAIN=local the test step failed
('requires go >= 1.25.0'). Install the exact version from go.mod via
go-version-file, bump the builder image to golang:1.25-alpine, and drop the stray
GOTOOLCHAIN override in build.ps1.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
go install goversioninfo@latest pulled a newer Go toolchain (1.26) that
mismatched setup-go's 1.24 and broke the resource step. Set GOTOOLCHAIN=local and
pin goversioninfo@v1.7.0 so the pinned toolchain builds the pinned tool.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Drop the obsolete CGO/mingw cross-compile machinery (all targets now build with
CGO off) and generate the Windows icon/version resource with goversioninfo before
building the windows/* binaries, so local builds match CI and finally embed the
icon the README advertises.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Make the Windows build produce a truly standalone .exe with no runtime
DLL prerequisites, and stop tracking a placeholder index.html that the
build pipeline rewrites on every run.
webui package
- Move the placeholder HTML out of a tracked file on disk and into a
placeholderHTML const in webui.go. serveIndex falls back to that
const when the embed does not contain index.html, so dev builds that
skip the frontend still get a sensible landing page.
- IsBuilt now checks for index.html instead of _next/ so the helper
stays accurate when only the placeholder is embedded.
Embed directory hygiene
- dist/.gitignore now ignores everything except itself; the directory
still exists for //go:embed but never shows dirty after a build.
- Stop tracking the old placeholder at dist/index.html.
scripts/build.ps1
- Staging step clears everything in dist/ except .gitignore (was also
preserving the old index.html).
- Windows amd64 builds now static-link the mingw-w64 C runtime via
-ldflags '-linkmode external -extldflags "-static"' so the final
orchestrad.exe depends only on standard Windows system DLLs and the
Universal CRT (part of Windows 10+). Verified: no libgcc_s_seh-1,
libstdc++-6, libwinpthread-1, msvcr*, or vcruntime140 imports.
- Auto-discover gcc from C:\ProgramData\mingw64, Chocolatey's mingw,
MSYS2 (ucrt64/mingw64), and TDM-GCC install locations so fresh
checkouts build without manual PATH edits after 'choco install mingw'.
- Windows arm64 is now skipped with a clear message when a matching
aarch64-w64-mingw32-gcc cross-compiler is not available, instead of
failing the whole run.
Binary impact (windows/amd64, CGO on, static): 24.06 MB.
Switch Next.js to static export (output: 'export', trailingSlash: true) and add a new backend/internal/webui package that embeds frontend/out/ via //go:embed. The backend now serves the UI from its own HTTP server with SPA fallback, long-lived cache headers on _next/static/*, and no dependency on a separate Node.js runtime or static host.
- frontend/next.config.mjs: output='export', trailingSlash=true, images.unoptimized.
- backend/internal/webui: Handler() with SPA fallback, resolve() mirroring Next trailing-slash behavior, IsBuilt() helper, and a placeholder dist/index.html so go build works without a prior frontend build. Top-level .gitignore tracks only the placeholder and its own .gitignore; the copied static export is ignored.
- backend/internal/server/server.go: mount webui.Handler() as the chi NotFound handler so /api/v1/* and /health continue to be served by their handlers while all other routes resolve through the embedded UI with SPA deep-link support.
- scripts/build.ps1: build the frontend (npm install if needed, then npm run build) before any Go build, stage frontend/out into backend/internal/webui/dist, and fail loudly if the UI output is missing or empty. Adds -SkipFrontend for developer iteration.
- Remove Spike demo content that prevented static export: api/* route handlers (dynamic POST/PUT/DELETE), apps/{blog,ecommerce,invoice} dynamic [slug]/[id] detail/edit pages, and frontend-pages/blog/[slug].
- Fix TypeScript errors surfaced by enabling the production build: ApiMeta.totalCount (not total) in audit and rule-runs pages; MUI v7 Grid uses size={{...}} instead of item+xs+md in config page.
Binary size grows from ~8 MB to ~37 MB, reflecting the embedded UI. The produced single binary is now sufficient to run the full product; no separate web server is required.
Phase 1 foundations:
- Go backend with Chi router framework
- SQLite database with WAL mode and foreign keys
- Database migrations for users, roles, credentials, AD connections, schedules, rules, and audit
- CLI commands: init, run, install, uninstall, start, stop, migrate, backup, restore, doctor
- Configuration loading from environment variables
- Centralized logging with file rotation (lumberjack)
- Crypto package for Argon2id password hashing and AES-GCM encryption
- Auth service with session management
- Audit service for event logging
- Scheduler with 6-field cron support
- REST API routes scaffolded for all major resources
- CORS support with localhost defaults for development
- Docker support with Dockerfile and docker-compose.yml
- Multi-platform build script (PowerShell)
- Project structure per design specification
Version format: yyyy.MM.dd.HHmm
All PKs are UUIDv4, all timestamps UTC