Thank you for your interest in contributing to AshReplicant!
Prerequisites
- Elixir 1.15+ and Erlang/OTP 26+
- A sibling checkout of
replicantat../replicant(path dependency during co-development) - PostgreSQL 14+ for integration tests (with
wal_level=logical); the integration suite runs against a live Postgres with a logical replication slot and publication
Getting Started
git clone https://github.com/baselabs/ash_replicant.git
cd ash_replicant
mix deps.get
mix test
Development Workflow
- Create a feature branch from
main. - Make your changes with clear, descriptive commit messages.
- Ensure all checks pass before opening a PR:
mix format
mix credo --strict
mix compile --warnings-as-errors
mix test
mix dialyzer
# or all gates at once:
mix quality
- Update
CHANGELOG.mdunder[Unreleased]. - Open a Pull Request against
main.
Ash conventions
- This is an Ash sink adapter — a
Spark.Dsl.Extensionimplementing theReplicant.Sinkbehaviour. Learn from the siblingash_postgresand the broader Ash extension ecosystem. - Read
AGENTS.mdbefore touching multitenancy, sensitive-data, or action-execution code — its Critical Rules are binding. - TDD: write the test first. Unit tests live in
test/; integration tests (marked with@moduletag :integration) live intest/integration/and require a live Postgres.
Critical rules (binding)
From AGENTS.md:
- Route writes through Ash actions, never raw Ecto. The resource's mirror action fires AshCloak encryption, policies, and multitenancy validation.
- Multitenancy is fail-closed. nil/blank tenant → error, never a base-tenant fallback.
- Sensitive = AshCloak-encrypted or binary or skip. Verified by compile-time verifier.
- Value-free at boundaries. No row values in errors, logs, or telemetry — ever, including halt paths.
- Tenant-blind layering. Multitenancy lives here;
replicantstays tenant-blind. - Effect-once = one transaction + watermark dedup + atomic checkpoint.
License
By contributing, you agree that your contributions will be licensed under the MIT License.