Expand description
Mandate — juridical delegation tracker (Story 3.4 — FR7 INV-14).
When a syndic must delegate a legal/technical act to an external
professional (notaire for a unit sale, avocat for a litigation,
architecte for renovation works, BET for technical studies, AMO for
project management assistance, gardien for on-site duties), they issue
a Mandate materialising:
- the mandataire (
subject_user_id), - the
kind(mapped to a Story 3.1UserRole), - the
scope(Building or whole ACP), - mandatory temporal validity (
valid_from/valid_until), - immutable audit (
issued_by,reason, timestamps), - optional early revocation (
revoked_at).
§Invariants enforced at issue() time
valid_until > valid_fromvalid_until - valid_from <= 5 years(anti-abuse: no unlimited mandates)reason.len() in [10, 500]subject_user_id != issued_by(a syndic may not mandate themselves)
Runtime helpers is_expired() / is_revoked() / is_currently_active()
are used by the upstream guard assert_mandate_authorizes to emit the
correctly-typed AppError::Mandate* (403/404) instead of generic
Forbidden strings.
Structs§
Enums§
- Mandate
Kind - Kind of mandate. Mapped to a
UserRole(Story 3.1) — issuing a mandate presumes the subject already carries the corresponding role. - Mandate
Scope - Scope a mandate applies to. Either a single building, or the whole ACP (e.g. a notaire mandated on all transactions of a copropriété).
Constants§
- MAX_
MANDATE_ DURATION_ DAYS - Anti-abuse: a single mandate cannot be active for more than 5 years.
Reissue (with a fresh
reason) keeps the audit trail granular. - MAX_
REASON_ LEN - Hard upper bound to keep DB rows compact and prevent free-form abuse.
- MIN_
REASON_ LEN - Minimal
reasonlength (Belgian deontological practice: a mandate without a stated motive is unenforceable in front of a juge de paix).