Skip to content
open-aviationPublic

About

A modern open-source publishing platform with good vibes

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

283 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

actaria

actaria is an open-source scholarly journal publishing platform: diamond open access, first-class open peer review, LaTeX-only submissions, and multi-tenant from day one.

See docs/superpowers/specs/ for design specs and docs/superpowers/plans/ for implementation plans.

See development status for the current release review, verification results, and remaining Phase 1 work. The release-readiness audit maps the original done criteria to current evidence and outstanding operator/provider acceptance.

Readers can use Search in a journal's navigation to find current articles, preprints and published review reports by title, abstract or keyword. Quoted phrases, OR and excluded terms (-term) are supported. Results use English word stemming and relevance ranking, with title matches weighted most strongly. Search follows the reader's publication/status rules and never searches private manuscripts or review provenance. Apply migrations when upgrading: publications migration 0012 adds the PostgreSQL full-text GIN index, maintained automatically as publication metadata changes.

Quickstart

The quickstart below is for development. For the separate production images, private credentials, HTTPS proxy and deployment validation, see production deployment. The backup and recovery guide covers consistent snapshots, off-site transfer, empty-target restore and delivery reconciliation.

Everything runs under Docker Compose: Postgres, Redis, MinIO, Django web, the RQ worker, and lightweight compile, Crossref, account-email and journal-email recovery services.

# First time, or after Dockerfile / dependency changes.
docker compose build

# Start the application, storage, worker and recovery services.
docker compose up -d

# Idempotent dev seed: migrations, license fixture, MinIO bucket, superuser,
# JOAS journal, sections, and manager role.
./scripts/init-joas-test.sh

# Build the Inertia/React bundle served by Django.
npm install
npm run build

After dependency rebuilds, recreate the affected application services with docker compose up -d --force-recreate --renew-anon-volumes <service> ... so their anonymous /opt/venv volumes receive the rebuilt dependencies. Compose otherwise preserves those volumes across image updates. Reinstall Playwright browsers and system dependencies when replacing the web container's test runtime.

Log in at http://localhost:8760/auth/login/:

  • Email: root@actaria.local
  • Password: actaria

Change the password before exposing the instance anywhere:

docker compose exec web uv run python manage.py changepassword root@actaria.local

If you are on a remote host over SSH, forward the port first:

ssh -L 8760:localhost:8760 <host>

Key URLs

After running ./scripts/init-joas-test.sh:

URL Purpose
/ Platform landing page listing configured journals
/admin/ Django admin, superuser only
/auth/login/ Email/password login
/auth/signup/ Email-first signup and verification
/auth/password-reset/ Request a password recovery email
/j/joas/ JOAS journal home
/j/joas/submit/ Author submission wizard
/j/joas/my-submissions/ Author submission list
/j/joas/office/ Editorial office dashboard
/j/joas/preprints/ Public preprint archive
/j/joas/preprint/<number>/ Public preprint detail
/j/joas/articles/ Public article index
/j/joas/article/<article-number>/ Public article detail
/healthz Process liveness without dependency access
/readyz Database, Redis and private storage readiness

The /j/<slug>/ prefix is configurable with ACTARIA_JOURNAL_PATH_PREFIX.

Common Development Commands

# Logs and service state.
docker compose logs -f web
docker compose ps

# Stop services. Data persists under ./data/.
docker compose down

# Stop services and remove the /opt/venv named volume.
docker compose down -v

# Rebuild the frontend bundle after editing resources/js or resources/css.
npm run build

# Vite dev server with HMR at http://localhost:5173/.
npm run dev

# TypeScript check.
npm run typecheck

Manual wizard test zip:

uv run scripts/build-example-zip.py

This writes example.zip containing main.tex, references, and a figure.

Testing

# Python unit/integration tests.
uv run pytest

# Browser UI tests.
uv run pytest tests/playwright/

# Docker integration tests, including real TeX Live compile cases.
uv run pytest -m docker

Playwright requires Chromium in the runtime where tests run:

uv run playwright install chromium

When services are already running, container execution is closest to the web runtime:

docker compose exec web uv run --frozen pytest
docker compose exec web uv run --frozen pytest tests/playwright/

# Real Docker/TeX tests use the compile worker's socket and scratch mount.
docker compose exec worker uv run --frozen pytest -m docker

The web service has no Docker socket. Run real compile integration tests in the worker, and run suites using the same test database sequentially.

CI measures application code, excluding tests and migrations, and requires 100% line coverage for permission modules and the workflow service/transition graph. Run the same coverage gate locally with:

docker compose exec web uv run --frozen pytest --cov=apps --cov-report=term-missing
docker compose exec web uv run --frozen coverage report --include='apps/*/permissions.py,apps/workflow/service.py,apps/workflow/stages.py' --fail-under=100

The overall release target remains 95%; current measured results and outstanding release work are tracked in Development status.

Configuration

Contributor roles and ROR affiliation lookup are documented in Contributor metadata and ROR. Optional ROR_CLIENT_ID identifies this installation to the organisation directory. Manual affiliation entry remains available when directory lookup fails.

  • .env is gitignored. Copy .env.example on first setup if you need local overrides.
  • Key variables: SECRET_KEY, DATABASE_URL, REDIS_URL, S3_ENDPOINT, S3_BUCKET, S3_ACCESS_KEY, S3_SECRET_KEY, ORCID_CLIENT_ID, ORCID_CLIENT_SECRET, ACTARIA_JOURNAL_PATH_PREFIX, ACTARIA_BASE_URL, CSRF_TRUSTED_ORIGINS, and ACTARIA_DATA_DIR.
  • docker-compose.yml overrides database, Redis, and S3 endpoints inside the Compose network.

When DEBUG=false, actaria refuses to start unless SECRET_KEY is a high-entropy value of at least 50 characters and ALLOWED_HOSTS contains explicit hostnames without the unrestricted * wildcard. Generate a key with:

uv run python -c "import secrets; print(secrets.token_urlsafe(64))"

Set that value and the production hostnames in the deployment environment before starting web, worker, or recovery processes.

Outbound email

Signup verification, contact verification and password recovery use durable account-email requests and the email worker. See account recovery operations for the trusted link origin, rate limits, recovery scheduler and operator diagnostics. Personal profiles verify contact addresses and manage ORCID connections at the configured platform origin. Reviewer invitations and existing editorial notifications use a tenant-scoped durable outbox with explicit resends for uncertain delivery. Submission participants can use private shared discussions and separate editorial notes, with attachment downloads and retained edit history. See discussion operations for audiences, participant access, reviewer identity handling and retention.

Authors and authorized editors can inspect private upload generations, compile logs and retained PDFs in Source history. See source-history operations for archive retention, released-source copies and the current-source backfill command for existing installs.

Public article, preprint and review-report pages offer version-specific BibTeX, RIS and EndNote downloads. See citation exports for metadata, privacy, custom domains and format behavior.

See journal email operations for recovery, permissions and legacy credential redaction. Managers choose initial submission-notification recipients under Office → Configurations → Email; none are selected automatically.

Configure SMTP_HOST, SMTP_PORT, SMTP_USER, and SMTP_PASSWORD for reviewer invitations and editorial decisions. For port 587, set SMTP_USE_TLS=true; for implicit TLS on port 465, use SMTP_USE_SSL=true instead. Set DEFAULT_FROM_EMAIL to a sender accepted by your mail server; a journal's configured From address overrides this fallback.

The equivalent Django variables (EMAIL_HOST, EMAIL_PORT, EMAIL_HOST_USER, EMAIL_HOST_PASSWORD, EMAIL_USE_TLS, EMAIL_USE_SSL) take precedence over the SMTP_* aliases. EMAIL_TIMEOUT defaults to 30 seconds. Restart web and worker processes after changing configuration.

For local development, EMAIL_BACKEND=django.core.mail.backends.console.EmailBackend prints messages to process logs. Use the SMTP backend for actual delivery.

Ports

Service Container port Host port Notes
web 8760 8760 Django
postgres 5432 6432 Localhost-only; avoids host Postgres collisions
redis 6379 6379 Localhost-only queue/cache
minio 9000 / 9001 9000 / 9001 Localhost-only API / console

The host ports are configurable with POSTGRES_PORT, REDIS_PORT, MINIO_PORT, and MINIO_CONSOLE_PORT. Development credentials can be overridden with POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB, S3_ACCESS_KEY, and S3_SECRET_KEY.

Data Persistence

Stateful services bind-mount under ./data/ by default:

./data/postgres
./data/redis
./data/minio

Set ACTARIA_DATA_DIR to keep data elsewhere. To wipe local dev data:

docker compose down
rm -rf data/

Compile Worker

The worker uses Docker-out-of-Docker: actaria-worker mounts the host Docker socket and starts sibling TeX Live containers for compile jobs. The scratch directory must exist on the host and be writable by UID 1000:

mkdir -p /tmp/actaria-compile

Important compile knobs:

Env var Default Notes
ACTARIA_TEXLIVE_IMAGE texlive/texlive:latest TeX Live image
ACTARIA_COMPILE_MEMORY 2g Per-compile memory cap
ACTARIA_COMPILE_CPUS 1 Per-compile CPU cap
ACTARIA_COMPILE_TIMEOUT 60 latexmk wall-clock timeout in seconds
ACTARIA_COMPILE_TMPFS_SIZE 512m /tmp inside sandbox
ACTARIA_COMPILE_USER 1000:1000 UID/GID inside sandbox
ACTARIA_COMPILE_LOG_CAP 262144 Retained compile-log bytes
ACTARIA_COMPILE_PDF_CAP 104857600 Maximum generated PDF bytes
ACTARIA_COMPILE_FILE_CAP 209715200 Kernel-enforced maximum bytes per sandbox file
ACTARIA_COMPILE_WORKDIR_CAP 536870912 Hard /work tmpfs byte cap
ACTARIA_COMPILE_STALE_SECONDS 300 Age at which a running job is recoverable
ACTARIA_COMPILE_RECOVERY_INTERVAL 60 Seconds between automatic recovery passes

Output collection closes its pipes and reaps the Docker client on both success and failure. Timeouts, output-limit errors, logging failures and worker cancellation also attempt to stop the named sibling container. That cleanup command is limited to ten seconds; Docker cleanup failure is logged without replacing the original compile error. The sandbox's own timeout and resource limits remain in force. Configured log caps also hold for very small values.

The compile-recovery Compose service runs stale-job recovery automatically. For an immediate one-off pass:

docker compose exec compile-recovery python manage.py recover_compile_jobs

Sandbox invariants are pinned by tests/test_sandbox_invariants.py: no network, read-only root filesystem and source bind, a size-capped tmpfs working directory, per-file resource limits, non-root user, and latexmk -no-shell-escape. The final PDF is size-checked inside the sandbox and streamed to the worker; TeX receives no writable host bind.

Known Limits

  • Manuscript zip: <= 20 MB compressed, <= 200 MB uncompressed, <= 500 entries.
  • Supplementary files: 20 MB each, 100 MB total per submission.
  • Output PDF: <= 100 MB.
  • PDFs and source artifacts are served through Django proxy views, not public presigned object-storage URLs.

Development Notes

  • Python dependencies are managed by uv.
  • Frontend source lives under resources/js/; Django serves the built bundle from static/dist/.
  • Always run npm run build after editing frontend source before relying on browser behavior through Django.
  • Pre-commit hooks run ruff, formatting, large-file checks, and the journal isolation-test gate. Enable them with uv run pre-commit install.

Publication snapshots

After upgrading an existing installation, apply migrations and run docker compose exec web uv run --frozen python manage.py snapshot_publications --apply to preserve existing public files and author metadata before reopening editorial access. New publications capture snapshots automatically. See publication snapshots and corrections for the dry run, recovery behavior, and version URLs.

DOI allocation

Configure the journal's DOI prefix and versioning policy in Office → Configurations → Identifiers. Production can reserve an identifier; publication also allocates one when configured. Reservations preserve version associations and remain distinct from confirmed registration. Crossref XML rendering, durable deposit attempts, editorial preview/submission controls and provider confirmation are implemented. Operators can enable automatic processing for future releases; the crossref-recovery service recovers queued work and checks provider results. Editors can explicitly associate imported DOIs with released versions while preserving their values and registration evidence. Released contributor names can be clarified with an immutable history to complete registration metadata. Retraction and withdrawal notices have independent DOIs and validated Crossmark updates; they wait for confirmation of the affected DOIs before submission. A provisioned Crossref test-account exercise remains a release requirement. See DOI operations for policy behavior and handling of legacy identifiers.

About

A modern open-source publishing platform with good vibes

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages