Files
acty ccb93eda21 docs(01): create phase 1 foundation plans
Phase 01: Foundation
- 2 plans in 2 waves
- Plan 01: Go project + Dockerfile (wave 1)
- Plan 02: Dev environment + verification (wave 2)
- Ready for execution

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-03 16:56:50 +09:00

203 lines
5.7 KiB
Markdown

---
phase: 01-foundation
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- go.mod
- go.sum
- cmd/server/main.go
- internal/health/handler.go
- docker/Dockerfile
- .dockerignore
autonomous: true
must_haves:
truths:
- "Go module initializes without errors"
- "Go server compiles to a single binary"
- "Docker image builds successfully for linux/amd64"
- "Built image is less than 150MB (debian slim + static binary)"
artifacts:
- path: "go.mod"
provides: "Go module definition"
contains: "module"
- path: "cmd/server/main.go"
provides: "Application entry point"
contains: "func main()"
- path: "internal/health/handler.go"
provides: "Health check endpoint handler"
contains: "func Handler"
- path: "docker/Dockerfile"
provides: "Multi-stage build definition"
contains: "FROM golang"
- path: ".dockerignore"
provides: "Build context exclusions"
contains: ".git"
key_links:
- from: "cmd/server/main.go"
to: "internal/health"
via: "import statement"
pattern: "internal/health"
- from: "docker/Dockerfile"
to: "cmd/server"
via: "go build command"
pattern: "go build.*cmd/server"
---
<objective>
Create Go project structure and multi-stage Dockerfile for isolated container builds.
Purpose: Establishes the foundational artifacts needed to build and run the Pirate Station backend. This plan creates the Go module with a minimal HTTP server and the multi-stage Dockerfile that produces a portable ARM64/x86_64 binary.
Output: Buildable Go project with Dockerfile that produces a slim container image.
</objective>
<execution_context>
@/home/acty/.claude/get-shit-done/workflows/execute-plan.md
@/home/acty/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/phases/01-foundation/01-CONTEXT.md
@.planning/phases/01-foundation/01-RESEARCH.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Initialize Go project with HTTP server</name>
<files>
go.mod
go.sum
cmd/server/main.go
internal/health/handler.go
</files>
<action>
1. Initialize Go module:
```bash
go mod init github.com/acty/pirate-station
```
(Use github.com path even though pushing to Gitea - conventional Go module naming)
2. Create cmd/server/main.go with:
- Import net/http and internal/health
- http.HandleFunc for "/" returning "Pirate Station API"
- http.HandleFunc for "/health" using health.Handler
- ListenAndServe on :32768
- log.Fatal on server error
- Log startup message with port number
3. Create internal/health/handler.go with:
- package health
- Handler(w http.ResponseWriter, r *http.Request) function
- Check os.Stat("/data") - return 503 if not exists
- Return 200 with {"status":"healthy"} JSON if /data exists
- Return 503 with {"status":"unhealthy","reason":"data volume not mounted"} if not
4. Run `go mod tidy` to create go.sum
Keep it minimal - no frameworks, no external dependencies, pure stdlib.
</action>
<verify>
```bash
go build -o /tmp/server ./cmd/server && echo "Build successful"
```
</verify>
<done>
- go.mod exists with module path
- cmd/server/main.go compiles
- internal/health/handler.go provides health check
- No external dependencies (only stdlib)
</done>
</task>
<task type="auto">
<name>Task 2: Create multi-stage Dockerfile</name>
<files>
docker/Dockerfile
.dockerignore
</files>
<action>
1. Create docker/Dockerfile with multi-stage build:
Build stage:
- FROM --platform=$BUILDPLATFORM golang:1.25-bookworm AS builder
- WORKDIR /build
- COPY go.mod go.sum ./ (cache dependencies separately)
- RUN go mod download
- COPY . .
- ARG TARGETOS TARGETARCH
- RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -ldflags="-w -s" -o /server ./cmd/server
Runtime stage:
- FROM debian:bookworm-slim
- RUN useradd -u 10001 -m appuser
- USER appuser
- COPY --from=builder /server /usr/local/bin/server
- VOLUME /data
- EXPOSE 32768
- CMD ["server"]
2. Create .dockerignore at project root:
```
.git
.gitignore
README.md
*.md
.env
.env.local
.DS_Store
.air.toml
docker-compose.yml
.planning/
tmp/
```
Key points:
- Use --platform=$BUILDPLATFORM for native build speed
- CGO_ENABLED=0 for static binary (no libc dependency)
- -ldflags="-w -s" strips debug symbols (smaller binary)
- Non-root user (appuser) for security
- VOLUME /data declares mount point
- Port 32768 as per user decision
</action>
<verify>
```bash
docker build -f docker/Dockerfile -t pirate-station:test . && docker images pirate-station:test --format "{{.Size}}"
```
Image should build and be under 150MB.
</verify>
<done>
- docker/Dockerfile exists with multi-stage build
- .dockerignore excludes non-essential files
- Image builds successfully
- Image size under 150MB (debian slim + Go binary)
</done>
</task>
</tasks>
<verification>
1. Go project compiles: `go build ./...`
2. Docker image builds: `docker build -f docker/Dockerfile -t pirate-station:test .`
3. Container starts: `docker run --rm -v /tmp/test-data:/data pirate-station:test &` then `curl localhost:32768/health`
4. Container cannot access host filesystem outside /data mount
</verification>
<success_criteria>
- Go module initialized with github.com/acty/pirate-station
- HTTP server listens on :32768
- /health endpoint returns JSON status
- Dockerfile produces working image under 150MB
- Image runs as non-root user
- No external Go dependencies (stdlib only)
</success_criteria>
<output>
After completion, create `.planning/phases/01-foundation/01-01-SUMMARY.md`
</output>