Files
AutopilotMonitor/src/Backend/AutopilotMonitor.Functions.Tests
Oliver Kieselbach 8862d73eed feat(backend+web): detect pre-approved consent for rights-less admins
In larger tenants the multi-tenant app is often pre-approved by someone
with consent rights, while the admin operating our UI lacks them. The
/adminconsent redirect then fails, so ValidateAutopilotDevice/
ValidateCorporateIdentifier never persist and the tenant stays "Disabled"
even though the app + DeviceManagementServiceConfig.Read.All effectively
exist. That bool is also the hard gate in SecurityValidator, so a UI-only
badge would leave agent traffic 403'd.

Add a read-only access-check probe that verifies the concrete role in the
SP token's roles claim (via GraphFeatureDetector, not mere token
acquirability) and, when present, persists the gate bool through the
normal config PUT — opening the UI badge AND the agent gate together.

Backend:
- GraphAppPermissions.DeviceManagementServiceConfigReadAll constant.
- GET /api/config/{tenantId}/autopilot-device-validation/access-check
  (TenantAdminOrGA): InvalidateTenant + fresh GetSnapshotAsync (4s budget),
  pure ResolveAccessPresent (transient => never present), emits
  ConsentAccessDetected telemetry. Always-fresh so a propagation-time
  empty-roles snapshot can't wedge the admin out for the token TTL.

Web:
- lib/accessCheck.ts classifyAccessCheck pure fn (transient/absent never
  reconcile) + tests.
- Reconcile on consent-redirect failure (silently enables) and a per-toggle
  "Detect existing access" button for Autopilot, Corporate, and DevPrep
  Device Association (all share the same role).
- Successful consent callback now verifies the concrete role too: persists
  ONLY on authoritative "reconciled"; transient => retry/propagation
  message, absent => "permission not granted" — neither opens the gate.
- saveConfiguration returns boolean so success is shown only after a
  confirmed persist.

No ConfigVersion bump (backend + web only). Backend 2326/2326, web 464/464.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 18:41:34 +02:00
..
2026-04-25 12:26:34 +02:00
2026-04-07 09:50:59 +02:00
2026-04-01 02:39:11 +02:00
2026-05-20 19:54:43 +02:00
2026-03-31 22:29:24 +02:00
2026-04-02 22:43:44 +02:00