1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//! The tenant-scoped lookup contract the CRUD route macros call.
use async_trait;
use crateFrameworkError;
/// A model that can be looked up scoped to a tenant.
///
/// `#[resource_get]` / `#[resource_post]` emit a call to
/// `<Self as TenantScoped>::find_for_tenant(id, tenant.id)`. Because every
/// generated lookup passes the resolved `tenant_id`, a generated handler
/// cannot read a row owned by another tenant — implementations MUST include
/// `tenant_id` in the query predicate.
///
/// Implement with `#[async_trait]` (re-exported as `ferro::async_trait`):
///
/// ```ignore
/// #[ferro::async_trait]
/// impl TenantScoped for Customer {
/// type Id = i64;
/// async fn find_for_tenant(id: i64, tenant_id: i64)
/// -> Result<Option<Self>, ferro::FrameworkError> {
/// // SELECT * FROM customers WHERE id = ? AND tenant_id = ?
/// }
/// }
/// ```