Implements RBAC-based write gating for Intune restore flows, UI affordances, and audit logging; adds tests and specs.
2.8 KiB
2.8 KiB
Data Model — Provider Access Hardening v1 (Intune Write Gate)
Entities (existing)
Tenant
Used as the persisted source of truth for the gate.
tenants.rbac_status(nullable string)- Expected values used by this feature:
null,not_configured,ok,degraded,failed
- Expected values used by this feature:
tenants.rbac_status_reason(nullable string)- Human-readable/safe explanation from last check / setup.
tenants.rbac_last_checked_at(nullable timestamp)- Used for freshness evaluation.
Relationships:
Tenant→ hasManyAuditLogTenant→ hasManyOperationRun(tenant-scoped runs)
OperationRun
Used to record outcomes for queued/async work.
operation_runs.type- Existing types touched by this feature (no new types introduced):
restore.executeassignments.restore- health checks: reuse existing verification/provider connection check type(s)
- Existing types touched by this feature (no new types introduced):
operation_runs.failures/ failure metadata- Must include stable reason codes when gate blocks a queued job.
RestoreRun
Represents the restore workflow state and links to an OperationRun.
restore_runs.operation_run_id(FK tooperation_runs)restore_runs.statustransitions drive UX and notifications.
AuditLog
Used to record UI-level blocked write attempts (P3 in spec).
- Must store stable
action(e.g.,intune_rbac.write_blocked) - Must store tenant scope and sanitized metadata (no tokens, no raw Graph payloads)
Domain Objects (new / feature-scoped)
IntuneRbacWriteGate (service)
- Inputs:
Tenant, operation identifier (string), “write class” operation - Output: allowed or throws a domain exception containing:
reason_code: one ofintune_rbac.not_configuredintune_rbac.unhealthyintune_rbac.stale
reason_message: sanitized, user-facing message
Freshness rule:
- Evaluate staleness by comparing
tenant.rbac_last_checked_attonow() - threshold. - Threshold is configurable (default 24 hours).
Config toggle:
- If disabled, gate always allows but logs a warning per evaluation (observability).
ProviderAccessHardeningRequired (exception)
- Carries tenant + operation + reason code + safe message.
- Used by both start surfaces (to present UX) and jobs (to fail
OperationRunsafely).
State transitions (gate perspective)
- Allowed:
rbac_status = okANDrbac_last_checked_atis within freshness threshold. - Blocked — Not configured:
rbac_status is nullORrbac_status = not_configured. - Blocked — Unhealthy:
rbac_status in {degraded, failed}. - Blocked — Stale:
rbac_status = okbutrbac_last_checked_atis older than threshold.
Validation & safety rules
- Gate evaluation must be DB-only (no Graph calls).
- Blocked paths must ensure zero Graph write calls.
- Failure metadata must be sanitized and stable.