# Research: Orca v0.5 — Distribution Research findings for the v0.5 Distribution milestone (install, namespace, docker, public releases). Conducted during P0 RESEARCH under full autonomy. ## R-001: Gitea Container Registry **Source**: https://docs.gitea.com/usage/packages/container (Gitea 1.27.1 docs) **Findings**: - Gitea ships a built-in OCI-compliant container registry. - Image naming convention: `{registry}/{owner}/{image}:{tag}`. For orca: `git.cloudinit.dev/coreci/orca:{tag}`. - Auth: `docker login git.cloudinit.dev` with username + personal access token (or password if no 2FA). The `GITEA_TOKEN` env var already used for release publishing works as the password. - Push: `docker push git.cloudinit.dev/coreci/orca:v0.4.4`. - Pull: anonymous pull works **if the repo is public** (REQ-045 flips this). For private repos, pull requires auth. - Tags are case-insensitive — use lowercase image names. - The registry supports multi-arch manifests via `docker buildx`. **Implication for P03**: `scripts/release.sh` must add a `docker build` + `docker login` + `docker push` step. The `.coreci.yml` release pipeline needs a `container-publish` step. Credential is `GITEA_TOKEN` (reused from the existing release flow — no new secret needed). ## R-002: `tea repos edit` — Repo Visibility **Source**: `tea repos edit --help` (tea 0.14.1 installed locally) **Findings**: - Command: `tea repos edit --private false --repo coreci/orca` - The `--private` flag accepts `true`/`false` (string, not bool). - Default login `bot` (cloudinit-bot) is already configured and is the default login. No extra auth needed. - The change is immediate and reversible (re-run with `--private true`). **Implication for P0 ship**: Run this as an operational step during the P0 ship. Verify with unauth `curl` against the releases API afterward. ## R-003: Gitea Releases API — Asset Download URLs **Source**: `/api/v1/repos/coreci/orca/releases/latest` (authed probe) **Findings**: - Auth header format: `Authorization: token ` (NOT basic auth — basic auth returns "invalid username, password or token"). - Latest release endpoint: `GET /api/v1/repos/coreci/orca/releases/latest` → JSON with `tag_name`, `name`, `body`, `assets[]`. - Each asset has `browser_download_url` — the direct download URL. - **Public access**: once the repo is public (R-002), the releases API and asset downloads work **without authentication**. This is what `install.sh` relies on (REQ-043). - Asset naming convention from existing releases: `orca-{version}-linux-amd64.tar.gz` (per `scripts/release.sh`). **Implication for P02 install.sh**: 1. Query `GET /api/v1/repos/coreci/orca/releases/latest` (unauth, post-R-002). 2. Parse `tag_name` for the version. 3. Find the asset with `name` matching `orca-{tag}-linux-{arch}.tar.gz`. 4. Download `browser_download_url` with `curl -fsSL`. 5. Extract and install. ## R-004: ORCA_HOME Propagation Points (Codebase Audit) **Source**: `grep` for `UserHomeDir|os.Getenv("ORCA|\.orca` across `*.go` **Findings** — exactly 3 production code sites determine the namespace root today: | File | Current behavior | Needs change? | |------|-----------------|----------------| | `internal/certpaths/certpaths.go:21-26` | `Dir()` honors `ORCA_HOME` → `~/.orca` | **No** — this is the single source of truth. Already correct. | | `internal/store/store.go:13-19` | `Open("")` hardcodes `~/.orca/orca.db` (ignores `ORCA_HOME`) | **Yes** — route through `certpaths.DBPath()` instead. | | `internal/cli/init.go:16-22` | Hardcodes `~/.orca` via `os.UserHomeDir()` | **Yes** — route through `certpaths.Dir()`. | All other call sites (`node.go:openDB`, `daemon.go`, `job.go`, `doctor.go`, `cert.go`) already go through `certpaths.DBPath()` or `certpaths.Dir()` indirectly. **No other files need changes for REQ-041.** **For REQ-042 (`--system`)**: Add a `--system` persistent flag on `rootCmd`. When set, `rootCmd.PersistentPreRunE` sets `os.Setenv("ORCA_HOME", "/root/.orca")` before any subcommand runs. This is the minimal-touch approach — all downstream code already honors `ORCA_HOME`. The flag is a CLI convenience that maps to the env var, not a parallel mechanism. **Backward compatibility**: empty `ORCA_HOME` + no `--system` → `~/.orca` (unchanged). Existing tests that `t.Setenv("ORCA_HOME", ...)` continue to work. ## R-005: Distroless Base Image for CGO-free Go Binaries **Source**: Go module audit — `modernc.org/sqlite` (pure Go, CGO-free), `go.mod` has no CGO dependencies. **Findings**: - `gcr.io/distroless/static-debian12` is the correct base for static Go binaries with no CGO and no libc dependency. ~2MB image. - orca uses `modernc.org/sqlite` (pure Go) — no CGO, no libc. ✓ - Multi-stage Dockerfile: - Stage 1 (`golang:1.25`): build with `-trimpath -ldflags` (same as Makefile), output `bin/orca`. - Stage 2 (`gcr.io/distroless/static-debian12`): `COPY bin/orca /orca`, `ENTRYPOINT ["/orca"]`. - `CGO_ENABLED=0` must be set in the build stage to guarantee a static binary (Go defaults to CGO_ENABLED=1 on platforms with a C compiler). - The image runs as `nonroot` user by default in distroless — but orca writes to `~/.orca` (or `/root/.orca` for `--system`). For the container image, default `ORCA_HOME=/var/lib/orca` and document volume mount at that path. **Implication for P03**: Dockerfile is ~15 lines. The `.coreci.yml` release pipeline adds a `docker build --build-arg VERSION=$VERSION -t git.cloudinit.dev/coreci/orca:$VERSION .` step + login + push. ## R-006: install.sh Conventions (curl|sh pattern) **Source**: Common patterns from deno, rustup, homebrew installers. **Findings**: - 1-liner: `curl -fsSL | bash` (or `| bash -s -- --system`). - The script must be downloadable from a stable URL. orca's script lives at `scripts/install.sh` in the repo, accessible via `https://git.cloudinit.dev/coreci/orca/raw/branch/main/scripts/install.sh` (once repo is public per R-002). - Args passed via `bash -s -- --system --version v0.4.4`. - In-place update: detect existing binary at install path, read its version via `orca version --json` (parse `version` field), print "updated from X to Y", overwrite binary. **Never** touch the namespace dir (`~/.orca` or `/root/.orca`) — that's user state. - User-level default: `~/.local/bin/orca` (XDG-ish, on PATH on most modern distros). System-level: `/usr/local/bin/orca` (requires root). **Implication for P02**: install.sh is ~80-100 lines of bash. Idempotent. Tested via a `scripts/install_test.sh` that mocks the download and verifies path selection + update-in-place. ## Pitfalls (P-001..P-003) - **P-001**: `docker` may not be available in the CoreCI release pipeline container. The `.coreci.yml` release step uses `image: golang:1.25` which does NOT include docker. **Mitigation**: the release pipeline must use a `docker:dind` sidecar or a step image that has the docker CLI. Alternatively, `scripts/release.sh` handles docker publish only when run locally or in a CI step that has docker. The `.coreci.yml` container step must use an image with docker CLI (e.g., `catthehacker/docker:docker-latest` or a custom image). - **P-002**: Making the repo public exposes git history including the pre-existing `.env` SHA-1 leak (commit `00127ce` documented the rotate-forward decision; `.gitleaks-baseline.json` suppresses it for scanning). The leak is a **non-secret** (the token was rotated). This is an accepted risk per the existing decision — no new action needed, but document it in the P0 ship commit. - **P-003**: `CGO_ENABLED=0` must be explicit in the Dockerfile build stage. Without it, `go build` in `golang:1.25` may produce a dynamically-linked binary that won't run in distroless. Verified: orca has no CGO deps, but `CGO_ENABLED=0` is belt-and-suspenders.