# ---------- Builder ----------
FROM golang:1.26-bookworm AS builder

WORKDIR /src

# Cache modules first.
COPY go.mod go.sum ./
RUN go mod download

# Build the static (cgo-free, pure-Go sqlite) binary.
COPY . .
RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o /out/jarvis ./cmd/jarvis

# Install the sherlock credential broker + its MCP servers so the headless
# Copilot agent gets live read-only access to Grafana, Gitea, and hosts.
# Pinned to a released tag; the module is public so no auth is needed.
# GOPROXY=direct + GOSUMDB=off because it is served from Charlie's Gitea,
# not the public proxy/checksum database.
ARG SHERLOCK_VERSION=v0.1.11
RUN GOBIN=/out GOFLAGS=-trimpath GOPROXY=direct GOSUMDB=off CGO_ENABLED=0 \
    go install \
      gitea.alexandru.macocian.me/amacocian/sherlock/cmd/sherlock@${SHERLOCK_VERSION} \
      gitea.alexandru.macocian.me/amacocian/sherlock/cmd/grafana-mcp@${SHERLOCK_VERSION} \
      gitea.alexandru.macocian.me/amacocian/sherlock/cmd/gitea-mcp@${SHERLOCK_VERSION} \
      gitea.alexandru.macocian.me/amacocian/sherlock/cmd/gssh-mcp@${SHERLOCK_VERSION}

# ---------- Runtime ----------
# node base image so the GitHub Copilot CLI (a Node package) runs headless.
FROM node:22-bookworm-slim AS runtime

# Runtime deps: git (clone Charlie repos for context), ca-certs, jq (parse
# the Gitea API in the entrypoint), tini (PID 1 signal handling), gosu (drop
# privileges to the jarvis user after fixing the bind-mount ownership),
# gettext-base (envsubst, to render the sherlock config from env), libcap2-bin
# (setcap: grant the jarvis binary CAP_SETUID/SETGID so it can drop the agent
# to a separate unprivileged user without the whole service running as root).
RUN apt-get update \
    && apt-get install -y --no-install-recommends git ca-certificates jq tini curl gosu gettext-base libcap2-bin \
    && rm -rf /var/lib/apt/lists/*

# Install the GitHub Copilot CLI globally (provides the `copilot` binary).
RUN npm install -g @github/copilot && npm cache clean --force

# Two unprivileged users:
#   jarvis  (10001) runs the service and owns /data (the SQLite DB).
#   copilot (10002) runs the --yolo agent + MCP subprocess tree, confined to
#           its own writable home; the mirrored repos are mounted read-only.
# /context holds the cloned repos (locked read-only at startup by the
# entrypoint); /data holds the SQLite DB.
RUN useradd --create-home --uid 10001 jarvis \
    && useradd --create-home --uid 10002 copilot \
    && mkdir -p /context /data \
    && chown -R jarvis:jarvis /context /data

COPY --from=builder /out/jarvis /usr/local/bin/jarvis
# Let the (non-root) jarvis service drop the agent subprocess to the copilot
# user via setuid/setgid, while the service itself keeps running as jarvis.
RUN setcap cap_setuid,cap_setgid+ep /usr/local/bin/jarvis
# The mirrored repos are checked out root-owned and read-only; allow any user
# (the copilot agent) to run read-only git commands inside them.
RUN git config --system --add safe.directory '*'
# sherlock CLI + MCP servers on PATH so `sherlock copilot` can spawn them.
COPY --from=builder /out/sherlock /out/grafana-mcp /out/gitea-mcp /out/gssh-mcp /usr/local/bin/
COPY docker/entrypoint.sh /usr/local/bin/entrypoint.sh
RUN chmod +x /usr/local/bin/entrypoint.sh

# The container starts as root so the entrypoint can chown the /data bind
# mount (which Docker creates root-owned on the host), then drops to the
# unprivileged jarvis user via gosu before running the service.
WORKDIR /context

ENV HOME="/home/jarvis" \
    JARVIS_LISTEN=":8080" \
    JARVIS_DB_PATH="/data/jarvis.db" \
    JARVIS_WORKDIR="/context" \
    JARVIS_AGENT_WORKDIR="/context/Charlie/project-charlie" \
    JARVIS_ADD_DIRS="/context" \
    JARVIS_COPILOT_USER="copilot" \
    GITEA_URL="https://gitea.alexandru.macocian.me" \
    GITEA_ORGS="Charlie" \
    GRAFANA_URL="https://grafana.alexandru.macocian.me" \
    GSSH_URL="https://terminal.alexandru.macocian.me" \
    SHERLOCK_ISSUER="https://id.alexandru.macocian.me/application/o/sherlock-cli/" \
    SHERLOCK_KEYRING="memory" \
    SHERLOCK_CONFIG="/home/copilot/.config/sherlock/config.toml"

EXPOSE 8080
VOLUME ["/data"]

ENTRYPOINT ["/usr/bin/tini", "--", "/usr/local/bin/entrypoint.sh"]
