Compile-verifier (build-blocking under --warnings-as-errors): a relationship's LOCAL join
attribute must not be sensitive. A sensitive attribute is app-side-encrypted binary
(ValidateSensitive R2); an encrypted-binary FK cannot be IN-joined — Slice-5 relationship
loading builds dest.<fk> IN [<plaintext pks>], so a sensitive join key silently breaks loading
and leaks via filter presence/absence. Fail closed, value-free (names the attribute atom only).
Coverage boundary (verified at Slice-5 closeout, 2026-07-08)
This verifier runs per-resource and flags a join attribute only when it is BOTH in the current
resource's own attribute set (local) AND its sensitive list. Coverage is therefore per-resource
and LOCAL:
belongs_to.source_attribute— local to the source (the FK lives here) → caught directly.many_to_manyjoin-resource FKs — local to the JOIN resource, which idiomatically declares them as thesource_attributeof its ownbelongs_toto each endpoint → caught by the JOIN resource's own run (NOT by the*_on_join_resourceslots below, which name attributes remote to the declaring resource and so never satisfy thelocalcheck — they are kept as defensive belt-and-suspenders, not the coverage mechanism).
KNOWN LIMITATION (routed follow-up → Slice 6): a has_many/has_one destination_attribute names an
attribute on the DESTINATION resource. It is caught here only when the destination independently
declares a relationship using that attribute as a LOCAL join key (the idiomatic inverse belongs_to).
A has_many/has_one whose sensitive destination_attribute has no such inverse is NOT caught at
compile (a per-resource Spark verifier cannot read a sibling resource's sensitive list without
compile-ordering fragility). Slice-6 adds a RUNTIME, LOAD-TIME guard (AshArcadic.Query.Filter
rejects a value comparison — including the relationship-load dest.<fk> IN [pks] — on a sensitive or
non-stored field), which converts the residual from a silent-[] load into a fail-closed loud
%UnsupportedFilter{}. That guard is load-time, not compile-time: a misconfigured resource still
compiles clean and fails only when the relationship is loaded.