# The bootstrap resolves this supported tag once and records an immutable digest.
ARG NODE_IMAGE
FROM ${NODE_IMAGE} AS build
# Compilers and development headers exist only in this disposable stage.
RUN apt-get update \
    && apt-get upgrade -y --no-install-recommends \
    && apt-get install -y --no-install-recommends gcc libc6-dev \
    && rm -rf /var/lib/apt/lists/*
WORKDIR /app
COPY package.json package-lock.json ./
RUN --mount=type=cache,id=dipersona-relay-npm,target=/root/.npm,sharing=locked npm ci --omit=dev --ignore-scripts --no-audit --no-fund
COPY deploy/dipersona-relay/webpki/package.json deploy/dipersona-relay/webpki/package-lock.json ./deploy/dipersona-relay/webpki/
RUN --mount=type=cache,id=dipersona-relay-npm,target=/root/.npm,sharing=locked cd deploy/dipersona-relay/webpki && npm ci --omit=dev --ignore-scripts --no-audit --no-fund
COPY src/ ./src/
COPY native/recovery-notify.c ./native/recovery-notify.c
COPY deploy/dipersona-relay/ ./deploy/dipersona-relay/
# Inspect installed dependency metadata. A legacy crypto dependency must never
# enter a newly built relay image, even through an alias or nested dependency.
RUN node deploy/dipersona-relay/webpki/verify-native-install.mjs
RUN cc -std=c11 -O2 -Wall -Wextra -Werror -Wpedantic -fPIC -fvisibility=hidden \
    -fstack-protector-strong -D_FORTIFY_SOURCE=2 -DNAPI_VERSION=8 \
    -DNODE_GYP_MODULE_NAME=inperson_recovery_notify -I/usr/local/include/node \
    -shared -pthread -Wl,-z,relro,-z,now,-z,noexecstack \
    -o native/recovery-notify.node native/recovery-notify.c \
    && chmod 0555 native/recovery-notify.node
RUN cc -std=c11 -O2 -Wall -Wextra -Werror -Wpedantic -fPIE -pie \
    -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack \
    -o deploy/dipersona-relay/docker/healthcheck deploy/dipersona-relay/docker/healthcheck.c \
    && chmod 0555 deploy/dipersona-relay/docker/healthcheck
RUN cc -std=c11 -O2 -Wall -Wextra -Werror -Wpedantic -fPIE -pie \
    -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wl,-z,relro,-z,now,-z,noexecstack \
    -o deploy/dipersona-relay/docker/healthcheck-direct deploy/dipersona-relay/docker/healthcheck-direct.c \
    && chmod 0555 deploy/dipersona-relay/docker/healthcheck-direct

FROM ${NODE_IMAGE}
# Runtime needs certificate tooling and flock, not a compiler, Python or npm.
# Updates are recorded in the immutable image inventory below. The Node-bundled
# OpenSSL is checked separately: upgrading Debian libssl does not replace it.
RUN apt-get update \
    && apt-get upgrade -y --no-install-recommends \
    && apt-get install -y --no-install-recommends ca-certificates openssl util-linux \
    && dpkg --compare-versions "$(dpkg-query -W -f='${Version}' libssl3t64)" ge '3.5.7-1~deb13u3' \
    && rm -rf /var/lib/apt/lists/* /usr/local/lib/node_modules/npm /usr/local/include/node /usr/local/lib/node_modules/corepack \
    && rm -f /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/corepack \
    && command -v openssl && command -v flock \
    && for tool in cc gcc g++ make python python3 npm npx corepack yarn pnpm; do ! command -v "$tool" || exit 1; done
WORKDIR /app
COPY --from=build --chown=0:0 /app /app
RUN node deploy/dipersona-relay/docker/runtime-policy.mjs \
    && mkdir -p /usr/local/share/dipersona \
    && dpkg-query -W -f='${binary:Package}\t${Version}\n' > /usr/local/share/dipersona/runtime-packages.tsv \
    && node -p 'JSON.stringify(process.versions)' > /usr/local/share/dipersona/node-versions.json
# The pinned bootstrap extracts source directories as root-only on the host.
# COPY preserves those modes. Only immutable image code becomes traversable;
# runtime state and secrets are excluded from the build and keep their own modes.
RUN find /app -type d -exec chmod 0755 {} + \
    && mkdir -p /run/role && chown 10001:10001 /run/role && chmod 0700 /run/role
USER 10001:10001
# Fail the build if the runtime user cannot read code or traverse a directory.
# Inspect metadata only: do not execute application code during the build.
RUN unreadable="$(find /app \( -type d ! -executable -o -type f ! -readable \) -print -quit)" \
    && test -z "$unreadable"
CMD ["node", "--disable-sigusr1", "/app/deploy/dipersona-relay/docker/transport-service.mjs", "ingress"]
