Add .clinerules for project conventions
This commit is contained in:
+97
@@ -0,0 +1,97 @@
|
||||
# Cline rules for the "beam" project
|
||||
|
||||
## Role
|
||||
|
||||
Act as an expert Go backend/web developer. This is a small, public-facing
|
||||
HTTP file-transfer service (upload/download via curl or a web UI). Prioritize
|
||||
idiomatic, stdlib-first Go, correctness, and security — anonymous users can
|
||||
upload arbitrary files, so treat all input as untrusted.
|
||||
|
||||
## Project architecture facts
|
||||
|
||||
- Single-file `main.go` using only the Go standard library (`net/http`,
|
||||
`html/template`, etc.) — no web framework, router, or third-party
|
||||
dependencies. Keep `go.mod` dependency-free unless the user explicitly
|
||||
approves adding one.
|
||||
- `index.html.tmpl` is the only frontend asset, rendered via `html/template`
|
||||
with inline CSS/JS. Keep it self-contained — no external asset build step,
|
||||
no CDN dependencies.
|
||||
- Configuration is via environment variables only (`UPLOAD_DIR`, `PORT`,
|
||||
`FILE_DURATION`, `DRYRUN_CLEAN`, `MAX_UPLOAD_SIZE`, etc.). Follow this
|
||||
pattern for any new configuration knob, validate it at startup with
|
||||
`log.Fatalf` on invalid values, log the effective value, and document it in
|
||||
`README.md`.
|
||||
- The background cleanup goroutine (`cleanupProcedure`) follows a
|
||||
dry-run-by-default, structured-logging pattern. Any new periodic
|
||||
background job should follow the same style: reset per-cycle state,
|
||||
dry-run support, and clear log messages for what was/would be done.
|
||||
|
||||
## Go version
|
||||
|
||||
- The toolchain version is pinned in `go.mod` (currently `go 1.27`). Match
|
||||
`go.mod` and the Dockerfile's `golang:X-alpine` builder image tag whenever
|
||||
bumping — never let the two drift apart. Don't use stdlib APIs newer than
|
||||
the pinned version.
|
||||
|
||||
## Kubernetes / TLS ingress deployment implications
|
||||
|
||||
This service runs in Kubernetes behind a TLS-terminating ingress.
|
||||
|
||||
- Never rely on `r.TLS != nil` to detect HTTPS. Always honor
|
||||
`X-Forwarded-Proto` / `X-Forwarded-Host` / `Forwarded` headers for any URL
|
||||
generation, matching the existing `getProtocol`/`getHost` helpers.
|
||||
- `/healthz` is used for k8s liveness/readiness probes: keep it fast and
|
||||
cheap (e.g. `os.Stat` on the upload dir is fine). Do not add slow checks,
|
||||
external calls, or heavy I/O to it.
|
||||
- The process receives SIGTERM on pod termination followed by SIGKILL after
|
||||
the grace period. Any new long-running goroutine or in-flight request
|
||||
handling must respect context cancellation / `srv.Shutdown` and not block
|
||||
graceful shutdown.
|
||||
- Assume horizontal scaling with multiple replicas: do not add in-memory
|
||||
state that must be shared/consistent across pods (e.g. in-memory rate
|
||||
limiting, sessions, counters) without explicitly calling out that it is
|
||||
per-pod-only and confirming that's acceptable.
|
||||
- `UPLOAD_DIR` may be backed by a PersistentVolume. Don't assume it's
|
||||
ephemeral, and don't assume it's shared across replicas (RWX) unless
|
||||
confirmed — flag this tradeoff if a feature depends on it.
|
||||
- The container runs as a non-root user (see Dockerfile `USER beam`). New
|
||||
code must not require root-only operations (binding privileged ports,
|
||||
chown, etc.).
|
||||
|
||||
## Coding conventions
|
||||
|
||||
- Always run `go build ./...`, `go vet ./...`, and `gofmt -l .` before
|
||||
considering a change complete; fix any findings.
|
||||
- Prefer the standard library over new dependencies (e.g. use `log/slog` if
|
||||
structured logging is ever introduced, rather than a third-party logger).
|
||||
- All path handling derived from user input (upload/download IDs,
|
||||
filenames) must be validated with `filepath.IsLocal` and/or
|
||||
`filepath.Clean`/`filepath.Base` before use — never trust raw path
|
||||
segments from the URL or multipart form.
|
||||
- All upload code paths must enforce `maxUploadSize` via
|
||||
`http.MaxBytesReader`, and clean up any partially written file/directory
|
||||
on failure.
|
||||
- New HTTP handlers must call `logRequest` with an accurate status code for
|
||||
every response path.
|
||||
- Keep the JSON error shape for `/upload` consistent with
|
||||
`writeMultipartError` (`{"error": "..."}`).
|
||||
|
||||
## Git workflow
|
||||
|
||||
- One logical change per commit.
|
||||
- Commit subject is a single line, no body.
|
||||
- Keep `.gitignore` up to date rather than leaving stray build/test
|
||||
artifacts untracked in the working tree.
|
||||
|
||||
## Testing
|
||||
|
||||
- There are currently no `*_test.go` files. When adding or changing logic
|
||||
that is easy to regress (path safety, ID generation, header parsing,
|
||||
upload size limits), add table-driven tests using the standard `testing`
|
||||
package and `net/http/httptest` where applicable.
|
||||
|
||||
## Documentation
|
||||
|
||||
- Keep `README.md` and the in-page instructions/labels in
|
||||
`index.html.tmpl` (e.g. max upload size, usage examples) in sync with
|
||||
actual runtime behavior.
|
||||
Reference in New Issue
Block a user