# WP5 — "Every setting carries its own permission" rule (BE)

## Goal
Formalize the owner's rule: a setting can declare the permission required to change it, checked per-setting on the write path. Add a nullable `permission` column to `setting_definitions`; when a setting's write is attempted, enforce that permission (falling back to the current `<module>.settings.manage` / `core.settings.manage` when null). Also fix the pre-existing duplicate-seed bug and document the convention.

## Exact files
- **Migration (create):** `/home/moonui2/moon-erp-be/Modules/Core/database/migrations/<new-ts>_add_permission_to_setting_definitions.php` — add `->string('permission', 100)->nullable()->after('scope')`. New timestamp must sort AFTER existing migrations. Run it on `moonui2_dev_be` in the SAME step (dev BE runs live). ⛔ never fresh/wipe.
- **Model:** `/home/moonui2/moon-erp-be/Modules/Core/app/Models/SettingDefinition.php` — add `permission` to `$fillable`.
- **Seeder:** `/home/moonui2/moon-erp-be/Modules/Core/database/seeders/SettingDefinitionSeeder.php` —
  1. **Fix pre-existing bug:** `accounting.ar_parent_account` is seeded TWICE → `UniqueConstraintViolationException` (baseline: 7 SettingApiTest failures). De-dupe it. After this, those 7 tests must go GREEN.
  2. Make the seeder upsert-safe (`updateOrCreate` on `setting_key`) so re-runs never 1062/UNIQUE-fail again.
  3. (Optional, incremental) set `permission` on a few high-value settings (e.g. financial account-mapping settings → the module's `.settings.manage`) as examples.
- **Write path (enforce):** `/home/moonui2/moon-erp-be/Modules/Core/app/Http/Controllers/SettingController.php` (methods `update`/`updateBulk`/`ensureDefaultAccounts`, gate at lines ~65-72). For each setting being written, if its definition has a non-null `permission`, assert `auth()->user()->can(...)`/Spatie `hasPermissionTo` for THAT permission; else keep the existing `core.settings.manage` gate. Return 403 with a clear message when the per-setting permission is missing.
- **Docs:** append the convention to `/home/moonui2/moon-erp-be/CLAUDE.md` (or the settings KB topic): "Any new SettingDefinition SHOULD declare its `permission`; a new setting ⇒ add the setting AND its permission."

## Interfaces
- **Consumes from WP2:** the 8 new `<module>.settings.manage` permissions (so per-module settings can be gated).
- **Exposes:** `setting_definitions.permission` column; write path enforces it per-setting.

## Acceptance criteria
- [ ] Migration adds nullable `permission`; run on `moonui2_dev_be` (no 1054 for dev users).
- [ ] `SettingDefinitionSeeder` de-duped + upsert-safe → the 7 baseline `SettingApiTest` failures GREEN.
- [ ] Writing a setting whose definition has `permission = X` without holding X → 403; with X → success. New test proves both.
- [ ] Convention documented.

## Tests
- BE: extend/repair `SettingApiTest` (should go from 7-failing to green after de-dupe); add a `SettingPermissionEnforcementTest` (per-setting 403/allow). Must not add NEW failures elsewhere.

## Flags
- **[FIN]** — yes (settings include GL account mappings; a wrong gate could expose financial config). Fable/advisor consult on the enforcement logic + the fallback semantics.
- **Migration:** YES — run same-step on `moonui2_dev_be`.

## Out of scope
- Do NOT retrofit `permission` onto ALL ~hundreds of settings — just the column + enforcement + a few examples + the de-dupe. Bulk classification is a later pass.
- Do NOT touch the roles screen or FE.
