feat(docker): add Coolify/deploy image for iris server - #29
Conversation
Multi-stage ARM64 image: rust:1.89-slim builder (openssl for lettre),
debian:bookworm-slim runtime, non-root iris user, /data volume for
attachments and audit log. Entrypoint materializes iris.toml from
IRIS_ENABLED_PROVIDERS at container start; secrets stay env-backed
({ env = ... } SecretValue), never baked into the image. A config
mounted at /etc/iris/iris.mounted.toml overrides generation.
Co-authored-by: Archon <archon@purelymail.com>
Entrypoint runs as non-root and cannot mkdir /etc/iris at runtime. Co-authored-by: Archon <archon@purelymail.com>
rust:1-slim now tracks trixie (glibc 2.39); binaries built there crash on the bookworm-slim runtime with GLIBC_2.39 not found. Co-authored-by: Archon <archon@purelymail.com>
Tag order is slim-bookworm, not bookworm-slim. Co-authored-by: Archon <archon@purelymail.com>
Auto-Merge Gate — Approval RationaleConfidence: 0.91 — MERGE (squash) Goal recovery: No linked Linear ticket; goal recovered from the PR body — make iris deployable via multi-stage Docker image (arm64/Hetzner fleet), env-driven entrypoint, Semantic verification performed (beyond CI):
Checks observed: Test, Format Check, Clippy, Secret Scan, Dependency Audit, Creed context drift — all SUCCESS on head Scope limits: 3 files, +129/−0, all new files — no Rust source touched, secrets env-only via Residual note: arm64 base resolution not exercised locally (x86_64 host); accepted on the author's builder-01 deploy-verification record. Build logic is arch-agnostic. Gate policy: standing gate per repo policy ( |
…IRIS-11 PR3) (#30) * feat: generated-surface attachment inputs for send_message (COD-406) Adopt hydra v0.2.0 json parameters: declare `attachments` in api/operations.yaml as a body json parameter carrying the closed inline/stored union schema plus CLI representation overrides (repeatable --attach with companion --attach-mime). Regenerate CLI/MCP artifacts and pin hydra to tag v0.2.0. Runtime decoding lives in iris-core::wire (pure, no I/O): - decode_attachments: union -> OutboundAttachment::Bytes/Stored, rejecting malformed base64, invalid UUIDs, empty inline bytes, missing MIME, mixed/unknown fields before any dispatch - plan_attachments: local-path vs iris://attachment/UUID split, --attach-mime cardinality (exactly one per local path, in order, stored refs consume none) with explicit override of extension inference HTTP routes and the MCP handler decode through the shared module (400 / JSON-RPC rejection on malformed unions); the CLI reads local files at the boundary and builds the OutboundMessage. Surface tests: HTTP 400 on mixed/unknown/bad-base64, MCP tool rejection, CLI flag parsing + boundary reads + mime override ordering, generated-schema union assertions, and a codegen freshness test mirroring `iris-codegen check`. 180/180 tests; build/clippy/fmt/codegen green. * chore: check off T8-T11 in add-outbound-attachments tasks * fix: reject null filename and blank --attach-mime overrides (review panel) Review panel findings on COD-406: - Reviewer B [MAJOR]: decode_item mapped explicit `filename: null` to None, widening the declared optional-but-not-nullable union schema. Now rejected before dispatch like any other unknown/malformed union member. - Reviewer A [MAJOR]: CLI --attach-mime overrides accepted empty/whitespace values while HTTP/MCP reject blank mime_type. plan_attachments now rejects blank overrides, keeping all three surfaces on the same contract. Both regression-tested in iris-core::wire. The panel's Docker-deletion BLOCK was a false positive caused by base drift: PR #29 added Docker files to main after this branch was cut; the rebase onto 0c6293c resolves it. No Docker files are touched by this branch.
Purpose
Make iris deployable: multi-stage Dockerfile (linux/arm64 target — Hetzner CAX fleet), env-driven entrypoint,
.dockerignore.What's in the image
rust:1.89-slim+ libssl-dev/pkg-config (lettre → native-tls chain). Cargo cache mounts for fast rebuilds.debian:bookworm-slim+ libssl3/ca-certificates, non-rootirisuser,/datavolume (attachments viaIRIS_ATTACHMENT_DIR, audit viaIRIS_AUDIT_DIR).iris.tomlfromIRIS_ENABLED_PROVIDERS(comma list: mock/telegram/email/sms). All secrets env-backed via iris's{ env = ... }SecretValue — nothing baked into the image. A full config mounted at/etc/iris/iris.mounted.tomloverrides generation.iris serve --addr 0.0.0.0:9876,/healthendpoint.Environment tested
Verification
/healthrespondsdocker inspectshowsArchitecture: arm64