intent/bin/start
Alec Perkins 99f810d043 Harden auth, invites and deployment after security review
- Signed-out visitors get the same login redirect for missing and
  private projects, so the redirect no longer reveals private ones.
- Production refuses the console email backend; sign-in codes must
  never reach the logs.
- Database cache shared by all workers for allauth rate limits; invite
  sending throttled per sender and per recipient.
- Email invite links are claimed on first use and the token rotated,
  so a token copied from request logs is worthless.
- allauth password URLs removed; adding an email requires a fresh code
  and notifies existing addresses.
- Markdown drops remote images until uploads exist.
- Project and org slugs lowercased; only superusers can grant staff
  status or permissions in the admin.
- Container runs as a non-root user; CI actions pinned to commits.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-27 08:42:19 -04:00

26 lines
1,001 B
Bash
Executable file

#!/bin/sh
# Production entrypoint. Migrations run here rather than in Fly's release_command,
# because release machines don't mount the volume that holds the SQLite database.
set -eu
# The volume is mounted owned by root. Take ownership for the app user, then rerun as it.
if [ "$(id -u)" = 0 ]; then
chown -R app:app "${INTENT_DATA_DIR:?}"
exec setpriv --reuid=app --regid=app --init-groups env HOME=/home/app "$0" "$@"
fi
DB="${INTENT_DATA_DIR:?}/db.sqlite3"
SERVER="gunicorn config.wsgi --bind 0.0.0.0:8000 --workers 3 --access-logfile -"
if [ -z "${LITESTREAM_BUCKET:-}" ]; then
echo "LITESTREAM_BUCKET not set: running without backups" >&2
python manage.py migrate --noinput
python manage.py createcachetable
exec $SERVER
fi
# On a fresh volume, pull the latest backup before anything touches the database.
litestream restore -if-db-not-exists -if-replica-exists "$DB"
python manage.py migrate --noinput
python manage.py createcachetable
exec litestream replicate -exec "$SERVER"