# Real signal-cli, for verifying celilo's client against the actual JSON-RPC
# interface rather than against a simulator that encodes our assumptions.
#
# The account is never linked. That is deliberate and sufficient: signal-cli's
# HTTP interface is served locally and does not touch Signal's network, so the
# endpoint paths, envelope shapes, error shapes, SSE receive stream, and the
# Host/Content-Type guards are all verifiable without an account.
#
# What an unlinked daemon CANNOT verify is that a linked account delivers a
# message to a phone. That needs Signal's real network. DNS is ours in e2e and
# even the TLS trust store is a swappable classpath resource (`whisper.store`,
# password "whisper" — see StagingConfig.java), but CDSI/SVR2 use SGX remote
# attestation whose whole purpose is to make substitution impossible. That
# limit is real; everything short of it is not.
#
# Three facts learned by RUNNING this rather than reading about it:
#   - signal-cli 0.14.6 ships class-file version 69, so it needs a Java 25 JRE.
#     A 21 base dies at startup with UnsupportedClassVersionError.
#   - it needs the native libsignal-client (signal_jni), which upstream ships
#     for x86_64 only — as is the "Linux-native" build. This image was pinned
#     to linux/amd64 for that reason and ran under qemu on our arm64 hosts.
#     It is not pinned any more (celilo#422): on arm64 it installs the native
#     we build ourselves, the same .deb the signal module installs on the
#     fleet, so the contract test runs against the daemon natively.
#   - extracting the tarball inside an emulated stage fails under qemu
#     ("Cannot mkdir: Function not implemented"), so the fetch runs on the
#     builder's own architecture and only the files cross over.

ARG SIGNAL_CLI_VERSION=0.14.6

FROM --platform=$BUILDPLATFORM debian:bookworm-slim@sha256:3783cc01769c7b2b1b83a5c5ad96c815348e28ed7da68e2e3687004faa906251 AS fetch
ARG SIGNAL_CLI_VERSION
RUN apt-get update \
    && apt-get install -y --no-install-recommends curl ca-certificates \
    && rm -rf /var/lib/apt/lists/*
# Fetched at BUILD time — the e2e network is sealed at run time.
RUN curl -fsSL \
      "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}.tar.gz" \
      -o /tmp/signal-cli.tar.gz \
    && mkdir -p /out \
    && tar -xzf /tmp/signal-cli.tar.gz -C /out \
    && mv "/out/signal-cli-${SIGNAL_CLI_VERSION}" /out/signal-cli
# The published JSON schemas are the authoritative description of the JSON-RPC
# surface — a test can assert against them rather than against prose.
RUN curl -fsSL \
      "https://github.com/AsamK/signal-cli/releases/download/v${SIGNAL_CLI_VERSION}/signal-cli-${SIGNAL_CLI_VERSION}-json-schemas.tar.gz" \
      -o /tmp/schemas.tar.gz \
    && mkdir -p /out/schemas \
    && tar -xzf /tmp/schemas.tar.gz -C /out/schemas

# No --platform: the digest is a multi-arch index (linux/amd64 and linux/arm64
# among others), so this resolves to the builder's own architecture.
FROM eclipse-temurin:25-jre@sha256:bb036ed6cfdc57e3da7c22634d15f1b840d2caf76183861c80e81ca4b5104abb
ARG TARGETARCH
COPY --from=fetch /out/signal-cli /opt/signal-cli
COPY --from=fetch /out/schemas /opt/signal-cli-schemas

# The linux-aarch64 native. `cele2e build-infra` builds it from the module's own
# recipe (scripts/stage-libsignal.ts) and copies exactly that .deb into
# .signal-cli-native/. The directory is tracked, with a README, so it is in the
# build context on every host; on x86_64 the README is all it holds. Not the
# apt pool: a COPY from a pool path with nothing in it failed the amd64 build,
# because nothing under that path reached the context (celilo#422).
COPY .signal-cli-native/ /tmp/libsignal/
# A missing .deb on arm64 warns and carries on, to match stage-libsignal.ts: a
# native that could not be built must not break build-infra for every other
# suite. The daemon then refuses to start, and signal-contract.test.ts is what
# fails, naming the native.
# More than one staged is refused, not resolved: stage-libsignal.ts stages
# exactly the version signal-cli's JAR expects, and picking among several by
# sort order would install the oldest.
RUN set -eu; \
    debs="$(ls /tmp/libsignal/libsignal-jni_*_arm64.deb 2>/dev/null || true)"; \
    if [ "$(printf '%s\n' "${debs}" | grep -c .)" -gt 1 ]; then \
      echo "ERROR: more than one libsignal-jni arm64 .deb is staged; expected exactly the one stage-libsignal.ts names:" >&2; \
      printf '%s\n' "${debs}" >&2; \
      exit 1; \
    fi; \
    deb="${debs}"; \
    if [ "${TARGETARCH}" = "arm64" ]; then \
      if [ -n "${deb}" ]; then \
        dpkg -i "${deb}"; \
      else \
        echo "WARNING: no libsignal-jni arm64 .deb was staged in .signal-cli-native; signal-cli cannot start in this image." >&2; \
      fi; \
    fi; \
    rm -rf /tmp/libsignal
# Where that .deb puts libsignal_jni.so. Harmless on x86_64, where the JAR's
# own bundled native is found first. The same setting as the module's systemd
# unit (signal-cli.service.j2).
ENV JAVA_OPTS="-Djava.library.path=/usr/lib"

ENV PATH="/opt/signal-cli/bin:${PATH}"
ENV SIGNAL_CLI_DATA=/var/lib/signal-cli
RUN mkdir -p "${SIGNAL_CLI_DATA}"

EXPOSE 8080

# Bound to 0.0.0.0 so the Host-header pin is skipped for in-network callers
# (HttpServerHandler.isHostAllowed). The container only ever sits on the sealed
# e2e network.
CMD ["signal-cli", "--config", "/var/lib/signal-cli", "daemon", "--http", "0.0.0.0:8080"]
