fix: CustomField policies, no system-actor fallback, guidelines
- Tests and UI pass actor for CustomField create/read/destroy; seeds use actor - Member required-custom-fields validation uses context.actor only (no fallback) - CODE_GUIDELINES: add rule forbidding system-actor fallbacks
This commit is contained in:
parent
250369d142
commit
21dbdbe366
10 changed files with 116 additions and 43 deletions
|
|
@ -683,6 +683,13 @@ end
|
|||
- Falls back to admin user from seeds if system user doesn't exist
|
||||
- Should NEVER be used for user-initiated actions (only systemic operations)
|
||||
|
||||
**DO NOT use system actor as a fallback:**
|
||||
|
||||
- **Never** fall back to `Mv.Helpers.SystemActor.get_system_actor()` when an actor is missing or nil (e.g. in validations, changes, or when reading from context).
|
||||
- Fallbacks hide bugs (callers forget to pass actor) and can cause privilege escalation (unauthenticated or low-privilege paths run with system rights).
|
||||
- If no actor is available, fail explicitly (validation error, Forbidden, or clear error message). Fix the caller to pass the correct actor instead of adding a fallback.
|
||||
- Use system actor only where the operation is **explicitly** a systemic operation (see list above); never as a "safety net" when actor is absent.
|
||||
|
||||
**User Mode vs System Mode:**
|
||||
|
||||
- **User Mode**: User-initiated actions use the actual user actor, policies are enforced
|
||||
|
|
@ -1658,6 +1665,30 @@ end
|
|||
|
||||
## 5. Security Guidelines
|
||||
|
||||
### 5.0 No system-actor fallbacks (mandatory)
|
||||
|
||||
**Do not use the system actor as a fallback when an actor is missing.**
|
||||
|
||||
Examples of forbidden patterns:
|
||||
|
||||
```elixir
|
||||
# ❌ FORBIDDEN - Fallback to system actor when actor is nil
|
||||
actor = Map.get(changeset.context, :actor) || Mv.Helpers.SystemActor.get_system_actor()
|
||||
|
||||
# ❌ FORBIDDEN - "Safety" fallback in validations, changes, or helpers
|
||||
actor = opts[:actor] || Mv.Helpers.SystemActor.get_system_actor()
|
||||
|
||||
# ❌ FORBIDDEN - Default actor in function options
|
||||
def list_something(opts \\ []) do
|
||||
actor = Keyword.get(opts, :actor) || Mv.Helpers.SystemActor.get_system_actor()
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
||||
**Why:** Fallbacks hide missing-actor bugs and can lead to privilege escalation (e.g. a request without actor would run with system privileges). Always require the caller to pass the actor for user-facing or context-dependent operations; if none is available, return an error or fail validation instead of using the system actor.
|
||||
|
||||
**Allowed:** Use the system actor only where the operation is **by design** a systemic operation (e.g. email sync, seeds, test fixtures, background jobs) and you explicitly call `SystemActor.get_system_actor()` at that call site—never as a fallback when `actor` is nil or absent.
|
||||
|
||||
### 5.1 Authentication & Authorization
|
||||
|
||||
**Use AshAuthentication:**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue