You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Implements the read-only-rootfs item deferred at backend-deploy.yml (the old
note at :263-265): the serving container now runs --read-only, and the deploy
ships a pre-cutover gate that validates the FULL boot under the exact flags
before cutover, closing the "gate exits before the app phase" gap that forced
the deferral.
ExecStart + gate both gain --read-only and the shared tmpfs set:
/tmp (rw,size=512m,mode=1777) Chromium temp profiles + shm redirect,
nft mktemp, /tmp/fingpt_cache
/app/staticfiles (uid=1001,gid=1001) collectstatic at boot
/home/fingpt (uid=1001,gid=1001) fontconfig, ~/.edgar, yfinance (uid pin
or the #331 MCP-child EACCES returns)
/app/logs + /app/media stay non-tmpfs on purpose: zero writers today, so a
future stray write must fail LOUDLY. /dev/shm is podman-managed and unaffected.
Gate redesign (entrypoint.sh BOOT_CHECK_ONLY=1, wrapping the final exec):
probes every writable surface + $HOME (covers the fail-SOFT MCP-child writes
/health/ can never catch), backgrounds the image's own CMD byte-identical (no
positional args on the podman line: zero-drift), polls /health/ inside the
container (~90s window), bounded SIGTERM+watchdog-SIGKILL shutdown. Subsumes
--egress-check-only, which stays for manual/local use. Deliberate asymmetries,
pinned by sentinels: gate /app/runtime is a THROWAWAY tmpfs (the real bind
mount's :U re-chown + os.replace() of the shared DuckDB are unsafe under the
serving container) and gate REDIS_URL uses throwaway DB15. Accepted residual:
the :U/:Z relabel path (#322 class) stays covered only by the post-cutover
~130s health window. Deploy step gets an explicit command_timeout: 20m.
Dockerfile: pre-bake Playwright's DEPENDENCIES_VALIDATED marker via a real
one-time chromium launch as uid1001 (the driver's marker write is fail-soft
under --read-only but would force per-process revalidation), with a loud
test -f build guard.
Also fixes the pre-existing prod break where /api/sync_preferred_urls/ (used
by the shipped extension) 500s: /app/data is root-owned, so the manager write
EACCESes. Storage path is now env-configurable (PREFERRED_LINKS_PATH), pinned
to /app/runtime/preferred_links.json in the image, seeded on first use from
the in-image default file; local dev keeps the in-repo path.
Sentinels extended in test_dockerfile_nonroot.py (flag extractor widened to
tmpfs/memory/read-only with equals-form pinning, parity + closed asymmetry
list, frozen tmpfs target sets, boot-check branch structure, marker bake) and
new tests/test_preferred_links_manager.py (env override, seeding, fallback,
write path, Dockerfile pin).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
0 commit comments