## 0. Scope, ownership, and file-purpose annotations

| File | File purpose (plain language) | Ownership / collision boundary |
|---|---|---|
| `backend/src/main/java/com/xyw/console/auth/SystemUserAdminService.java` | Changes an account and invalidates its old login only when effective authorization changes. | Authentication change; coordinate with current account-permission work. |
| `backend/src/main/java/com/xyw/console/auth/PagePermissionService.java` | Provides reusable server-side administrator verification for the protected device API. | Authentication change; preserve existing page-permission semantics. |
| `backend/src/main/java/com/xyw/console/config/SecurityConfig.java` | Maps security-layer authentication, CSRF, and authorization failures to safe browser responses. | Authentication change; do not relax CSRF or global protection. |
| `backend/src/main/java/com/xyw/console/asset/controller/DeviceAssetController.java` | Requires an administrator before list, lookup, image, and CRUD device requests reach the service. | Device integration; preserve service and DTO contracts. |
| `backend/src/test/java/com/xyw/console/auth/SystemUserAdminServiceTest.java` | Proves version changes and account-management role boundaries without a live database. | New focused test file. |
| `backend/src/test/java/com/xyw/console/config/SecurityConfigTest.java` | Proves safe response categories for expired sessions, CSRF failures, and ordinary permission denial. | New focused test file. |
| `backend/src/test/java/com/xyw/console/asset/controller/DeviceAssetControllerTest.java` | Proves administrators pass and ordinary accounts cannot bypass device API protection. | Extend existing device test file. |
| `frontend/src/modules/auth/auth-api-client.js` | Is the shared browser helper that sends cookies, fetches CSRF input, and preserves multipart requests. | Authentication change; all API clients depend on it. |
| `frontend/src/modules/auth/auth-store.js` | Clears browser identity and navigates to login after a shared request reports an invalid session. | Authentication change; avoid circular module dependencies. |
| `frontend/src/modules/device/device-api-client.js` | Sends device list, lookup, CRUD, and image requests through the shared authenticated helper. | Device integration only; do not change device view behavior. |
| `frontend/tests/auth-session-consistency.spec.js` | Exercises stale-session, CSRF, and multipart browser request behavior. | New focused browser test. |
| `frontend/tests/device-asset.spec.js` | Extends device workflow tests with real request-header and multipart-boundary assertions. | Device integration test; preserve existing scenarios. |

- [x] 0.1 Confirm the active authentication and device working-tree changes, preserve unrelated edits, and designate one integration owner for the four shared files above. Integration owner: current authorization/session change.
- [x] 0.2 Add a plain-language file-purpose annotation to each new test file. For every method, callback, or helper added or changed in the scoped files, add a beginner comment describing its purpose, related files, and request-to-security-to-response data flow.
- [x] 0.3 Do not run a database migration or modify `as_system_user` schema; verify `auth_version` is already readable and writable before implementation.

## 1. Authorization-session consistency

- [x] 1.1 Add focused helpers in `SystemUserAdminService` that compare persisted and requested role, status, and normalized page permissions, and calculate the next `auth_version` safely from the persisted value.
- [x] 1.2 Update `SystemUserAdminService.updateUser` so a true authorization-state change increments `auth_version` in the same row update, while a no-op update does not invalidate the current session.
- [x] 1.3 Keep existing developer/super-administrator creation boundaries unchanged; a fresh `DEVELOPER` token can manage accounts, a valid non-administrator token remains denied, and no additional developer account can be created.
- [x] 1.4 Update `SecurityConfig` to return safe distinct messages for invalidated/absent login sessions, missing-or-invalid CSRF input, and valid-session authorization denial, without returning account, role, permission, token, or exception details.
- [x] 1.5 Add and annotate a reusable administrator requirement in `PagePermissionService`; apply it in every `DeviceAssetController` endpoint, including company-person lookup and opaque image reads, while preserving the approved administrator-only device scope.

## 2. Shared device write authentication

- [x] 2.1 Update `auth-api-client.js` request handling to preserve caller headers, send credentials, initialize CSRF for protected writes, and omit a forced JSON `Content-Type` when the request body is `FormData`.
- [x] 2.1a Change CSRF initialization to verify the real `XSRF-TOKEN` Cookie instead of trusting an in-memory ready flag, and have a 401 signal `auth-store.js` to clear local identity and navigate to login without repeating the request.
- [x] 2.2 Refactor every `device-api-client.js` operation to use the shared authenticated request helper; retain existing URLs, query parameter behavior, and API response shape.
- [x] 2.3 Verify device multipart create and update retain the browser-generated boundary, and device delete includes the CSRF header and cookie.
- [x] 2.4 Ensure a 401 session-invalid response clears local authentication state and leads the user to sign in again; do not silently retry a write that might repeat a user action.

## 3. Focused verification

- [x] 3.1 Add `SystemUserAdminServiceTest` coverage for role promotion, status change, permission change, no-op update, developer management success, and non-administrator denial. Annotate every test method and business callback.
- [x] 3.2 Add `SecurityConfigTest` coverage for 401 expired-session handling, CSRF 403 handling, ordinary authorization 403 handling, and the absence of sensitive details. Extend `DeviceAssetControllerTest` with administrator allow and ordinary-user denial coverage for list, lookup, image, and all CRUD operations. Annotate every test method and callback.
- [x] 3.3 Add browser coverage for the first device write obtaining CSRF, Cookie-absence reacquisition, multipart request header/boundary behavior, device delete CSRF behavior, 401 login redirect, and the safe refresh-and-retry message. Annotate every test method and route callback.
- [x] 3.4 Run `mvn -q test`, `npm run build`, focused authentication/device Playwright tests, and the existing full frontend Playwright suite. Diagnose a failing check before changing code.
- [x] 3.5 Record changed files, no-database-impact confirmation, security behavior, executed verification, and any unexecuted check in the completion handoff.

## Completion handoff (2026-08-03)

### Changed files

- Backend authorization: `SystemUserAdminService`, `PagePermissionService`, `SecurityConfig`, and `DeviceAssetController`.
- Backend tests: `SystemUserAdminServiceTest`, `SecurityConfigTest`, and extended `DeviceAssetControllerTest`.
- Frontend authentication/device requests: `auth-api-client.js`, `auth-store.js`, and `device-api-client.js`.
- Frontend tests: `authenticated-test.js` and `device-asset.spec.js`.

### Security behavior delivered

- Account role, status, or normalized page-permission changes increment `auth_version`; the previous token fails on its next protected request and the browser returns to login.
- Device list, lookup, opaque image read, create, update, and delete operations require `DEVELOPER` or `SUPER_ADMIN` in the backend, not only a protected route or hidden menu.
- Device multipart writes use the shared authenticated CSRF request helper. The helper preserves browser multipart boundaries, reacquires a missing `XSRF-TOKEN` Cookie, and does not retry a rejected write.
- CSRF rejection reports safe refresh-and-retry guidance; valid-session authorization denial remains generic.

### Database and configuration impact

- No database migration, DDL, direct database write, or configuration-file change was performed. The existing `auth_version` entity field and migration definition are reused.

### Executed verification

- `mvn -q -Dtest=SystemUserAdminServiceTest,SecurityConfigTest,DeviceAssetControllerTest test` passed.
- `mvn -q test` passed.
- `npm run build` passed, retaining only existing third-party PURE-comment and bundle-size warnings.
- `npx playwright test tests/device-asset.spec.js --config=playwright.device.config.js --reporter=list --timeout=30000` passed: 6/6.
- `npx playwright test --config=playwright.device.config.js --reporter=list --timeout=30000` passed: 14/14.
- `openspec validate fix-auth-session-and-device-csrf --strict` passed.

### Unexecuted checks

- No live production write was performed. After backend restart, manually log out and log in once, then verify account creation and device create/update/delete using the developer account.
