TenantAtlas/docs/HANDOVER.md
2026-03-07 17:41:55 +01:00

40 KiB
Raw Blame History

TenantPilot / TenantAtlas — Handover Document

Generated: 2026-03-06 · Branch: dev · HEAD: da1adbd Stack: Laravel 12 · Filament v5 · Livewire v4 · PostgreSQL 16 · Tailwind v4 · Pest 4


Executive Summary

  • Product: Enterprise Intune Governance SaaS — backup, version-control, restore, drift detection, and observability for Microsoft Intune policy configurations across multiple tenants.
  • Core value prop: Immutable JSONB policy snapshots, restore wizard with dry-run/preview, inventory-first drift detection against Golden Master baselines, workspace-scoped RBAC, and alert/evidence pipeline.
  • 28+ Intune policy types supported (device config, settings catalog, compliance, app protection, conditional access, scripts, enrollment, endpoint security, update rings, etc.) — defined in config/tenantpilot.php.
  • Maturity: Production-capable MVP with ~109 specs, 708 test files (582 Feature + 125 Unit + 1 Deprecation), extensive guard tests, and an architectural constitution document.
  • Three Filament panels: /admin (workspace-tenant context), /admin/t (tenant-scoped), /system (platform operator console).
  • Workspace-first multi-tenancy: All data is workspace-isolated. Tenants belong to workspaces. Non-members get 404 (deny-as-not-found).
  • Capability-first RBAC: ~40+ capabilities in a canonical registry (app/Support/Auth/Capabilities.php), enforced server-side with UI enforcement helpers.
  • Operations system: Unified OperationRun model with 25+ run types, idempotent creation, stale-run detection, 3-surface feedback (toast → progress → DB notification).
  • Baseline/Drift engine: 4-spec progression (116→119) — meta-fidelity v1 → content-fidelity v1.5 → full evidence capture v2 → legacy drift cutover. All 4 specs implemented on dev.
  • Key open areas: Formal release grouping (R1/R2/R3) exists only as brainstorming; missing: exception/risk-acceptance workflows, compliance evidence packs, cross-tenant promotion, MSP portfolio dashboard, change approval workflows.
  • Biggest risk: No .env.example in repo; Dokploy deployment config is external; no formal CI pipeline config in repo.

Product & Roadmap Snapshot

What exists (fully implemented on dev)

Domain Status Key Specs
Policy Sync (28+ types) Implemented 001030
Immutable PolicyVersions (JSONB) Implemented Core
BackupSets + BackupItems Implemented 005, 006, 016
Restore Wizard (dry-run, preview, execute) Implemented 011, 023, 049
Assignments backup/restore + group mapping Implemented 004, 006, 094
Settings Catalog readable names Implemented 003, 045
Inventory sync + coverage matrix Implemented 039042
Dependency graph (inventory_links) Implemented 042, 079
OperationRun unified monitoring Implemented 053, 054, 055, 078
Provider connections + gateway Implemented 061, 081, 089, 108
Entra OIDC sign-in Implemented 063, 064
Workspace + Tenant RBAC Implemented 062, 065, 066, 070072
Managed tenant onboarding wizard Implemented 073
Verification checklist Implemented 074, 075, 084
Backup scheduling + retention Implemented 032, 091
Alerts v1 (Teams + Email) Implemented 099, 100
Baseline governance (Golden Master) Implemented 101, 115119
Findings lifecycle + SLA Implemented 044, 111
Permission posture + Entra admin roles Implemented 104, 105
Review pack export (CSV+ZIP) Implemented 109
Settings (workspace + tenant) Implemented 097, 098
System console + control tower Implemented 113, 114
Platform ops runbooks Implemented 113
Unified badges + tag catalog Implemented 059, 060
Legacy purge (bulk ops, old runs) Implemented 056, 086088, 092

Roadmap (from brainstorming — specs/0800-future-features/brainstorming.md)

Priority order: MSP Portfolio + Alerting > Drift + Approvals > Standardisierung/Linting > Promotion DEV→PROD > Recovery Confidence

Release Theme Items Code exists?
R1 "Golden Master Governance" Baseline drift as production feature Baseline capture/compare/alerts, findings SLA, evidence capture Specs 101, 111, 115119 implemented
R1 cont. Operations polish OperationRun canonicalization, monitoring hub, action surfaces Specs 078, 082, 090, 110 implemented
R2 "Tenant Reviews & Evidence" Evidence packs, stored reports Review packs, permission posture, Entra admin roles, stored reports Partial — Specs 104, 105, 109 implemented; no formal "evidence pack" spec
R2 cont. Exception/risk-acceptance workflow Finding exceptions, risk acceptance tracking Missing — Finding model has risk_accepted status but no exception entity
R2 cont. Alert escalation + notification routing Alert rules per event type, quiet hours, cooldown Specs 099, 100 implemented
R3 "MSP Portfolio OS" Cross-tenant compare, portfolio dashboard Cross-tenant compare, MSP health dashboard, multi-workspace admin Spec 043 exists (draft), no implementation
R3 cont. Standardisierung / Policy linting Policy quality checks, duplicate finder, orphaned items Brainstorming only
Later Change approval workflows Approval gates before restore Brainstorming only
Later Recovery confidence Automated restore tests, readiness report Brainstorming only
Later Script & secrets governance Script diff/approval, secret scanning Brainstorming only
Later Security posture score Blast radius, opt-in high-risk Brainstorming only

Current Feature Map

Implemented

Feature UI Entrypoint Models Key Jobs DB Tables
Policy Sync PolicyResource Policy, PolicyVersion SyncPoliciesJob, CapturePolicySnapshotJob policies, policy_versions
Backup Sets BackupSetResource BackupSet, BackupItem AddPoliciesToBackupSetJob, RemovePoliciesFromBackupSetJob backup_sets, backup_items
Restore Wizard RestoreRunResource RestoreRun ExecuteRestoreRunJob, RestoreAssignmentsJob restore_runs
Backup Scheduling BackupScheduleResource BackupSchedule RunBackupScheduleJob, ApplyBackupScheduleRetentionJob backup_schedules
Inventory InventoryItemResource, InventoryCoverage page InventoryItem, InventoryLink RunInventorySyncJob, ProviderInventorySyncJob inventory_items, inventory_links
Findings FindingResource Finding CompareBaselineToTenantJob, GeneratePermissionPostureFindingsJob findings
Baselines BaselineProfileResource, BaselineSnapshotResource, BaselineCompareLanding BaselineProfile, BaselineSnapshot, BaselineSnapshotItem, BaselineTenantAssignment CaptureBaselineSnapshotJob, CompareBaselineToTenantJob baseline_profiles, baseline_snapshots, baseline_snapshot_items, baseline_tenant_assignments
Alerts AlertRuleResource, AlertDestinationResource, AlertDeliveryResource AlertRule, AlertDestination, AlertDelivery, AlertRuleDestination Jobs/Alerts/* alert_rules, alert_destinations, alert_deliveries, alert_rule_destinations
Operations Hub Operations page, TenantlessOperationRunViewer OperationRun All domain jobs operation_runs
Provider Connections ProviderConnectionResource ProviderConnection, ProviderCredential ProviderConnectionHealthCheckJob provider_connections, provider_credentials
RBAC ChooseWorkspace, ChooseTenant, NoAccess, BreakGlassRecovery Workspace, WorkspaceMembership, Tenant, TenantMembership, TenantRoleMapping RefreshTenantRbacHealthJob workspaces, workspace_memberships, tenants, tenant_memberships, tenant_role_mappings
Entra Groups EntraGroupResource EntraGroup EntraGroupSyncJob entra_groups
Verification TenantDiagnostics, TenantRequiredPermissions VerificationCheckAcknowledgement verification_check_acknowledgements
Permission Posture Via FindingResource Finding, StoredReport GeneratePermissionPostureFindingsJob, ScanEntraAdminRolesJob findings, stored_reports
Review Packs ReviewPackResource ReviewPack GenerateReviewPackJob review_packs
Settings WorkspaceSettings page WorkspaceSetting, TenantSetting workspace_settings, tenant_settings
Audit Log AuditLog page AuditLog audit_logs
System Console /system/dashboard, /system/ops/runbooks PlatformUser platform_users

Partial / In-Progress

Feature Status Gap
Cross-tenant compare Spec 043 drafted No implementation code
Policy lifecycle Spec 900 drafted Addresses ghost / orphaned policies — not yet implemented
Exception/Risk acceptance Finding has risk_accepted status No formal exception entity, no evidence attachment workflow

Missing (no code, no spec beyond brainstorming)

  • Change approval workflows / approval gates
  • Policy linting / standardization engine
  • Recovery confidence / automated restore tests
  • Script & secrets governance
  • Security posture scoring / blast radius
  • MSP portfolio health dashboard
  • Compliance light (formal compliance framework mapping)

Architecture & Principles (Non-Negotiables)

Source: .specify/memory/constitution.md (v1.10.0)

Core Principles

  1. Inventory-first, Snapshots-secondInventoryItem = last observed meta; PolicyVersion.snapshot = explicit immutable JSONB capture.
  2. Read/Write Separation — Analysis is read-only; writes require preview → dry-run → confirmation → audit log.
  3. Single Contract Path to Graph — All Microsoft Graph calls via GraphClientInterface (app/Services/Graph/GraphClientInterface.php); endpoints modeled in config/graph_contracts.php (867 lines, 28+ type definitions).
  4. Deterministic Capabilities — Backup/restore/risk flags derived from config via CoverageCapabilitiesResolver.
  5. Workspace Isolation — Non-member → 404; workspace is primary session context. Enforced via DenyNonMemberTenantAccess middleware + EnsureFilamentTenantSelected.
  6. Tenant Isolation — Every read/write must be tenant-scoped; DerivesWorkspaceIdFromTenant concern auto-fills workspace_id from tenant.

RBAC-UX Rules

Rule Description
UX-001 Server-side is source of truth (UI is never security boundary)
UX-002 Non-members get 404 (deny-as-not-found)
UX-003 Members without capability get 403
UX-004 Actions visible-but-disabled for members lacking capability; hidden for non-members
UX-005 All destructive actions require ->requiresConfirmation()
UX-006 Capabilities from canonical registry only (app/Support/Auth/Capabilities.php)
UX-007 Global search must be tenant-safe
UX-008 RBAC regression tests mandatory

Operations UX

  • 3-surface feedback: Toast (immediate) → Progress widget (polling) → DB notification (terminal).
  • OperationRun lifecycle: Service-owned transitions only via OperationRunService — no direct status writes.
  • Idempotent creation: Hash-based dedup with partial unique index.

Filament Standards

  • Action Surface Contract: List/View/Create/Edit pages each have defined required surfaces (Spec 082, 090).
  • Layout: Main/Aside layout, sections required, view pages use Infolists.
  • Badge Semantics: Centralized via BadgeCatalog/BadgeRenderer (Specs 059, 060).
  • No naked forms: Everything in sections/cards with proper enterprise IA.

Provider Gateway


Data Model Overview

Core Tables

Table Key Columns Notes
workspaces id, name, slug, archived_at Primary isolation boundary
workspace_memberships workspace_id, user_id, role Roles: Owner/Manager/Operator/Readonly
tenants id, workspace_id, tenant_id, external_id, name, status, is_current SoftDeletes; external_id = Azure tenant GUID
tenant_memberships tenant_id, user_id, role, created_by_user_id UUID PK
users Standard + entra_id, entra_name, is_platform_superadmin SoftDeletes
platform_users Separate from users /system panel auth guard

Policy & Versioning

Table Key Columns Notes
policies id, workspace_id, tenant_id, external_id, policy_type, display_name, odata_type, metadata (JSONB), ignored_at One row per Intune policy per tenant
policy_versions id, workspace_id, tenant_id, policy_id, version_number, snapshot (JSONB), metadata (JSONB), assignments (JSONB), content_hash, captured_at, capture_purpose Immutable snapshots; SoftDeletes
backup_sets id, workspace_id, tenant_id, name, status, metadata (JSONB) SoftDeletes
backup_items id, workspace_id, backup_set_id, policy_id, policy_version_id Links backup set to specific version
restore_runs id, workspace_id, tenant_id, backup_set_id, operation_run_id, status, is_dry_run, idempotency_key, requested_items (JSONB), preview (JSONB), results (JSONB), group_mapping (JSONB) SoftDeletes

Inventory & Dependencies

Table Key Columns Notes
inventory_items id, workspace_id, tenant_id, policy_type, external_id, display_name, meta_jsonb (JSONB), last_seen_at, last_seen_operation_run_id Current state from Graph
inventory_links id, workspace_id, source_type, source_id (text), target_type, target_id (text), relationship_type Dependency graph edges

Operations

Table Key Columns Notes
operation_runs id, workspace_id, tenant_id, user_id, type, status (queued/running/completed), outcome (pending/succeeded/partially_succeeded/blocked/failed), summary_counts (JSONB), failure_summary (JSONB), context (JSONB), started_at, completed_at Central run tracking for all async operations
audit_logs id, workspace_id, tenant_id, user_id, action, details (JSONB) Immutable audit trail

Baselines

Table Key Columns Notes
baseline_profiles id, workspace_id, name, status (draft/active/archived), capture_mode, scope_jsonb (JSONB), active_snapshot_id Golden Master definition
baseline_snapshots id, baseline_profile_id, operation_run_id, tenant_id, version_label, item_count Point-in-time snapshot
baseline_snapshot_items id, baseline_snapshot_id, policy_type, external_id, display_name, content_hash, meta_jsonb (JSONB), subject_key Individual policy item in snapshot
baseline_tenant_assignments id, baseline_profile_id, tenant_id Which tenants are compared against this baseline

Findings

Table Key Columns Notes
findings id, workspace_id, tenant_id, finding_type (drift/permission_posture/entra_admin_roles), severity, status, source, title, description, evidence_jsonb (JSONB), recurrence_key, fingerprint, first_seen_at, last_seen_at, times_seen, sla_days, due_at, evidence_fidelity, baseline_operation_run_id, current_operation_run_id Full lifecycle: new → triaged → in_progress → resolved/closed/risk_accepted

Alerts

Table Key Columns Notes
alert_destinations id, workspace_id, type (teams_webhook/email), config (JSONB) Where alerts go
alert_rules id, workspace_id, event_type, is_enabled, tenant_scope_mode, tenant_allowlist (JSONB), cooldown_seconds, quiet_hours_* When to alert
alert_rule_destinations alert_rule_id, alert_destination_id, workspace_id M:N join with workspace scope
alert_deliveries id, workspace_id, alert_rule_id, tenant_id, status, attempts, payload (JSONB) Delivery tracking with retry

Provider

Table Key Columns Notes
provider_connections id, workspace_id, tenant_id, provider, external_tenant_id, is_default, status, scopes_granted (JSONB), last_health_check_at Graph API connection per tenant
provider_credentials id, provider_connection_id, credential_type, client_id, client_secret (encrypted) Secrets storage

Other

Table Notes
stored_reports Permission posture + Entra admin roles reports, fingerprint dedup
review_packs Exportable audit artifact (ZIP), signed download URLs
backup_schedules Cron-based backup scheduling with retention keep_last
entra_groups Cached directory groups for assignment mapping
entra_role_definitions Cached Entra role definitions for admin roles evidence
settings_catalog_definitions / settings_catalog_categories Settings catalog human-readable name mapping
workspace_settings / tenant_settings Key-value settings with typed slices

Operations & Observability

OperationRun System

  • Central model: OperationRun (app/Models/OperationRun.php)
  • Type registry: OperationRunType enum (25+ types) (app/Support/OperationRunType.php)
  • Catalog: OperationCatalog — labels, expected durations, allowed summary keys (app/Support/OperationCatalog.php)
  • Lifecycle service: OperationRunService (877 lines) — idempotent ensureRun(), stale detection, state transitions, summary normalization (app/Services/OperationRunService.php)
  • Status: queuedrunningcompleted
  • Outcome: pending | succeeded | partially_succeeded | blocked | failed | cancelled (reserved)
  • Context: JSONB bag storing selection_hash, policy_types, categories, etc.

Monitoring UI

Scheduled Tasks (routes/console.php)

Schedule Frequency Job
Backup schedule dispatch Every minute tenantpilot:schedules:dispatch
Directory groups dispatch Every minute tenantpilot:directory-groups:dispatch
Alerts dispatch Every minute (no overlap) tenantpilot:alerts:dispatch
Prune old operations Daily PruneOldOperationRunsJob
Reconcile adapter runs Every 30 min ReconcileAdapterRunsJob
Stored reports prune Daily stored-reports:prune
Review pack prune Daily tenantpilot:review-pack:prune
Baseline evidence prune Daily tenantpilot:baseline-evidence:prune
Entra admin roles scan Daily (per tenant) ScanEntraAdminRolesJob

Security: Tenancy / RBAC / Auth

Three-panel architecture

Panel Path Guard Purpose
Admin /admin web Workspace + Tenant management (main UI)
Tenant /admin/t web Tenant-scoped views (within admin session)
System /system platform Platform operator console (separate cookies)

Auth flows

  • Entra OIDC: /auth/entra/redirect/auth/entra/callback (via Socialite)
  • Admin consent: /admin/consent/start/admin/consent/callback (app registration)
  • RBAC delegated auth: /admin/rbac/start/admin/rbac/callback
  • Break-glass: /system panel with BreakGlassRecovery page, config-gated TTL

Role hierarchy

Level Roles Source
Workspace Owner / Manager / Operator / Readonly app/Support/Auth/WorkspaceRole.php
Tenant Owner / Manager / Operator / Readonly app/Support/TenantRole.php
Platform Capabilities: access_system_panel, use_break_glass, console.*, ops.*, runbooks.* app/Support/Auth/PlatformCapabilities.php

Capability resolver chain

  • Capabilities::all() — reflection-based registry of ~40+ tenant/workspace capabilities
  • UiEnforcement (app/Support/Rbac/UiEnforcement.php) — builder pattern for Filament actions: forAction()->requireMembership()->requireCapability()->destructive()
  • WorkspaceUiEnforcement — mirror for workspace-scoped actions
  • 12 Laravel Policy classes in app/Policies/

Workspace isolation enforcement

  • DerivesWorkspaceIdFromTenant concern on models — auto-fills workspace_id
  • DB-level: NOT NULL + FK constraints on workspace_id for all tenant-owned tables (migration 2026_02_14_220114)
  • Check constraints on audit_logs (migration 2026_02_14_220117)
  • Middleware: ensure-workspace-selected, ensure-workspace-member, DenyNonMemberTenantAccess

Drift/Baseline/Findings: Current State & Gaps

Baseline Drift Engine (Specs 116119, all merged to dev)

Spec Title Status
116 Meta-fidelity + coverage guard Merged
117 Content-fidelity via provider chain (v1.5) Merged
118 Full content capture (v2) Merged
119 Drift cutover — legacy drift removal Merged

Architecture

  1. Capture: CaptureBaselineSnapshotJobBaselineCaptureService captures inventory metadata + optional full content evidence into baseline_snapshot_items.
  2. Compare: CompareBaselineToTenantJobBaselineCompareService compares snapshot against current tenant state. CurrentStateEvidenceProvider chain resolves best available evidence (content > meta).
  3. Findings: Creates/updates/auto-resolves Finding records with source = 'baseline.compare', finding_type = 'drift'.
  4. Evidence fidelity: evidence_fidelity field on findings tracks whether comparison was meta-level or content-level.
  5. Guard test: tests/Feature/Guards/Spec116OneEngineGuardTest.php, tests/Feature/Guards/Spec118NoLegacyBaselineDriftGuardTest.php — prevent regression to legacy drift patterns.

Findings lifecycle

  • Statuses: newacknowledgedtriagedin_progressresolved / closed / risk_acceptedreopened
  • SLA: FindingSlaPolicy computes due_at from workspace findings.sla_days setting
  • Auto-resolve: BaselineAutoCloseService resolves findings when drift disappears
  • Recurrence: recurrence_key + times_seen + first_seen_at / last_seen_at track repeating drift

Gaps

  • Exception entity: No formal FindingException model — only the risk_accepted status exists
  • Evidence pack: No formal evidence export spec as a standalone artifact (review pack covers partial ground)
  • Cross-tenant compare: Spec 043 drafted, not implemented — uses policy_type + normalized display_name matching

Testing & Tooling

Test suite

  • Framework: Pest 4 with RefreshDatabase
  • DB: SQLite :memory: (via phpunit.xml)
  • Test files: 582 Feature + 125 Unit + 1 Deprecation = 708 total
  • Infrastructure: tests/Pest.php (366 lines) — shared helpers: createUserWithTenant(), fakeIdToken(), bindFailHardGraphClient(), etc.

Key test categories

Category Path Count (approx)
Guard tests tests/Feature/Guards/ 14 files — enforce architectural rules via code scanning
RBAC tests tests/Feature/Rbac/, tests/Feature/TenantRBAC/ ~15 files
Baseline/Drift tests/Feature/BaselineDriftEngine/, tests/Feature/Baselines/, tests/Feature/Drift/ ~20 files
Operations tests/Feature/Operations/, tests/Feature/Monitoring/ ~10 files
Bulk operations tests/Feature/Bulk*Test.php ~20 files
Restore tests/Feature/Restore*Test.php ~15 files
Provider/Graph tests/Feature/ProviderConnections/, tests/Feature/Graph/, tests/Unit/Graph* ~15 files
Alerts tests/Feature/Alerts/, tests/Unit/Alerts/ ~10 files
Inventory tests/Feature/Inventory/, tests/Unit/Inventory/ ~15 files
Workspace isolation tests/Feature/WorkspaceIsolation/ ~5 files
Deprecation tests/Deprecation/ 1 file (is_platform_superadmin ban)

Guard tests (architectural enforcement)

These tests scan source code to prevent regressions:

Test Enforces
ActionSurfaceContractTest All resources have required action surfaces
NoAdHocFilamentAuthPatternsTest No ad-hoc auth patterns in Filament
NoAdHocStatusBadgesTest Use badge catalog, not ad-hoc badges
NoLegacyRunsTest No legacy run patterns in codebase
NoLegacyTenantGraphOptionsTest No legacy graph options usage
NoTenantCredentialRuntimeReadsSpec081Test No runtime credential reads
Spec116OneEngineGuardTest Single drift engine architecture
Spec118NoLegacyBaselineDriftGuardTest No legacy baseline drift code

Tooling

Tool Command Notes
Run all tests vendor/bin/sail artisan test --compact
Run specific file vendor/bin/sail artisan test --compact tests/Feature/SomeTest.php
Filter test vendor/bin/sail artisan test --compact --filter=testName
Pint formatter vendor/bin/sail bin pint --dirty Default Laravel preset
No .pint.json Uses default rules
No PHPStan config found UNKNOWN — check if integrated

Deployment & Runbooks

Local development

# Start services
vendor/bin/sail up -d

# Run migrations
vendor/bin/sail artisan migrate

# Start queue worker (or use docker-compose queue service)
vendor/bin/sail artisan queue:work --tries=3 --timeout=300

# Build frontend assets
vendor/bin/sail npm run build

# Run tests
vendor/bin/sail artisan test --compact

Docker services (docker-compose.yml)

Service Image Ports
laravel.test PHP 8.4 Sail 80, 5173 (Vite)
queue Same image queue:work --tries=3 --timeout=300 --sleep=3 --max-jobs=1000
pgsql PostgreSQL 16 5432
redis Redis 7 Alpine 6379

Deployment: Dokploy (staging → production)

  • No Dokploy config in repo — configuration lives on the VPS per Agents.md
  • Two environments: Staging (mandatory gate) → Production
  • Required env vars (partial — no .env.example):
    • Standard Laravel: APP_KEY, DB_*, REDIS_*, QUEUE_CONNECTION
    • Entra auth: AZURE_AD_CLIENT_ID, AZURE_AD_CLIENT_SECRET, AZURE_AD_TENANT_ID
    • Feature flags: BREAK_GLASS_ENABLED, ALLOW_ADMIN_MAINTENANCE_ACTIONS
    • Alerts: TENANTPILOT_ALERTS_ENABLED
    • Baselines: TENANTPILOT_BASELINE_FULL_CONTENT_CAPTURE_ENABLED
    • Write gate: TENANTPILOT_INTUNE_WRITE_GATE_ENABLED
  • Deploy checklist: php artisan migrate, php artisan filament:assets, queue restart

Platform runbooks


Risks & Gaps (Top 10)

# Risk Location Impact Suggested Action
1 No .env.example Repo root New dev can't set up without tribal knowledge Create .env.example with all required keys from config/*.php
2 No CI pipeline config in repo Missing No automated test gating on PRs Add Gitea CI / GitHub Actions config
3 No PHPStan/Larastan Missing Type-safety gaps undetected UNKNOWN — check if integrated; if not, add baseline
4 Exception/risk-acceptance workflow incomplete Finding.STATUS_RISK_ACCEPTED exists, no exception entity Can't track formal risk acceptances with evidence Spec needed for FindingException model with approval chain
5 SQLite for tests vs PostgreSQL in prod phpunit.xml JSONB, GIN indexes, PG-specific features untested Add phpunit.pgsql.xml — file exists but may not be in CI
6 No formal release process Roadmap only in brainstorming doc No versioned release artifacts, no changelog Define release cadence and changelog automation
7 Dokploy config external Per Agents.md Deployment not reproducible from repo alone Document or codify Dokploy config
8 Cross-tenant compare unimplemented Spec 043 draft only Key MSP feature missing Prioritize for next sprint if MSP use case is active
9 Policy lifecycle / ghost policies Spec 900 draft only Deleted-in-Intune policies persist indefinitely Implement orphan detection + soft-archive flow
10 Break-glass recovery surface Config-gated, TTL-limited Limited testing evidence Verify break-glass flow has smoke tests in test suite

Next Actions (Top 5)

  1. Create .env.example — Document all required env vars from config/*.php files. Low effort, high impact for onboarding.

  2. Add CI pipeline — Gitea / runner config for vendor/bin/sail artisan test --compact + vendor/bin/sail bin pint --test on every PR. Critical for sustained quality.

  3. Formal exception/risk-acceptance spec — Design FindingException entity with approval chain, evidence attachment, and UI workflow. Blocks R2 "Evidence Packs" roadmap item.

  4. PostgreSQL test mode — Enable phpunit.pgsql.xml in CI for a subset of tests that exercise JSONB/GIN-specific behavior.

  5. Cross-tenant compare implementation (Spec 043) — Build read-only compare view first (N=2 tenants). This is the first step toward the MSP portfolio use case.


Appendix

Specs Index (109 specs)

# Slug Status
001 rbac-onboarding Implemented
003 settings-catalog-readable Implemented
004 assignments-scope-tags Implemented
005 bulk-operations Implemented
006 sot-foundations-assignments Implemented
007 device-config-compliance Implemented
008 apps-app-management Implemented
009 app-protection-policy Implemented
011 restore-run-wizard Implemented
012 windows-update-rings Implemented
013 scripts-management Implemented
014 enrollment-autopilot Implemented
017 policy-types-mam-endpoint-security-baselines Implemented
018 driver-updates-wufb Implemented
023 endpoint-security-restore Implemented
024 terms-and-conditions Implemented
026 custom-compliance-scripts Implemented
027 enrollment-config-subtypes Implemented
028 device-categories Implemented
029 wip-policies Implemented
030 intune-rbac-backup Implemented
031 tenant-portfolio-context-switch Implemented
039 inventory-program Meta-spec (040044)
040 inventory-core Implemented
041 inventory-ui Implemented
043 cross-tenant-compare-and-promotion 📋 Draft
045 settingscatalog-classification Implemented
049 backup-restore-job-orchestration Implemented
051 entra-group-directory-cache Implemented
052 async-add-policies Implemented
053 unify-runs-monitoring Implemented
054 unify-runs-suitewide Implemented
055 ops-ux-rollout Implemented
058 tenant-ui-polish Implemented
059 unified-badges Implemented
060 tag-badge-catalog Implemented
061 provider-foundation Implemented
062 tenant-rbac-v1 Implemented
063 entra-signin Implemented
064 auth-structure Implemented
065 tenant-rbac-v1 Implemented
070 workspace-create-membership-fix Implemented
071 tenant-selection-workspace-scope Implemented
072 managed-tenants-workspace-enforcement Implemented
074 verification-checklist Implemented
077 workspace-nav-monitoring-hub Implemented
078 operations-tenantless-canonical Implemented
079 inventory-links-non-uuid-ids Implemented
081 provider-connection-cutover Implemented
084 verification-surfaces-unification Implemented
085 tenant-operate-hub Implemented
086 retire-legacy-runs-into-operation-runs Implemented
087 legacy-runs-removal Implemented
088 remove-tenant-graphoptions-legacy Implemented
089 provider-connections-tenantless-ui Implemented
091 backupschedule-retention-lifecycle Implemented
092 legacy-purge-final Implemented
093 scope-001-workspace-id-isolation Implemented
094 assignment-ops-observability-hardening Implemented
095 graph-contracts-registry-completeness Implemented
096 ops-polish-assignment-dedupe-system-tracking Implemented
097 settings-foundation Implemented
098 settings-slices-v1-backup-drift-ops Implemented
099 alerts-v1-teams-email Implemented
100 alert-target-test-actions Implemented
101 golden-master-baseline-governance-v1 Implemented
102 filament-5-2-1-upgrade Implemented
103 ia-scope-filter-semantics Implemented
104 provider-permission-posture Implemented
105 entra-admin-roles-evidence-findings Implemented
106 required-permissions-sidebar-context Implemented
107 workspace-chooser Implemented
108 provider-access-hardening Implemented
109 review-pack-export Implemented
110 ops-ux-enforcement Implemented
111 findings-workflow-sla Implemented
112 list-expand-parity Implemented
113 platform-ops-runbooks Implemented
114 system-console-control-tower Implemented
115 baseline-operability-alerts Implemented
116 baseline-drift-engine (meta v1) Implemented
117 baseline-drift-engine (content v1.5) Implemented
118 baseline-drift-engine (full capture v2) Implemented
119 baseline-drift-engine (cutover) Implemented
700 bugfix Implemented
900 policy-lifecycle 📋 Draft
0800 future-features (brainstorming) 📋 Brainstorming

Specs not listed above (e.g., 002, 010, 015, 016, 025, 032, 042, 044, 046048, 056057, 066067, 073, 075076, 080, 082083, 090, 999) have spec directories but were not individually verified. Based on merge history and code presence, the vast majority are implemented.

Key File Map (Top 20 files to read first)

File Why
.specify/memory/constitution.md Non-negotiable architectural rules
Agents.md Agent workflow, branching, environment
config/tenantpilot.php 28+ policy types, feature flags, all config
config/graph_contracts.php Graph API contract registry (867 lines)
app/Support/Auth/Capabilities.php Canonical RBAC capability registry
app/Support/OperationRunType.php All operation run types
app/Support/OperationCatalog.php Labels, durations, summary keys
app/Services/OperationRunService.php Central run lifecycle (877 lines)
app/Support/Rbac/UiEnforcement.php RBAC UI enforcement builder (678 lines)
app/Services/Providers/ProviderGateway.php Graph API facade
app/Services/Providers/ProviderConnectionResolver.php Connection resolution + validation
app/Services/Baselines/BaselineCompareService.php Drift comparison engine
app/Services/Baselines/BaselineCaptureService.php Snapshot capture
app/Models/Finding.php Finding lifecycle model
app/Models/OperationRun.php Central run model
app/Models/Tenant.php Tenant model (320 lines)
routes/web.php All routes (3 panels, auth, workspace)
routes/console.php Scheduler definitions
tests/Pest.php Test helpers & infrastructure
specs/0800-future-features/brainstorming.md Future roadmap ideas

Key Commands

# Local dev
vendor/bin/sail up -d                          # Start all services
vendor/bin/sail artisan migrate                # Run migrations
vendor/bin/sail artisan queue:work --tries=3   # Process queue
vendor/bin/sail npm run build                  # Build frontend

# Testing
vendor/bin/sail artisan test --compact                           # Full suite
vendor/bin/sail artisan test --compact --filter=testName         # Single test
vendor/bin/sail artisan test --compact tests/Feature/Guards/     # Guard tests only

# Code quality
vendor/bin/sail bin pint --dirty               # Format changed files

# Deployment
vendor/bin/sail artisan filament:assets        # Publish Filament assets
vendor/bin/sail artisan migrate --force        # Production migration

Quickstart (exact steps)

  1. Clone repo, cd TenantAtlas
  2. cp .env.example .env (MISSING — create from config files or request from team)
  3. composer install
  4. vendor/bin/sail up -d
  5. vendor/bin/sail artisan key:generate
  6. vendor/bin/sail artisan migrate
  7. vendor/bin/sail npm install && vendor/bin/sail npm run build
  8. vendor/bin/sail artisan filament:assets
  9. Login: Navigate to /admin — redirects to workspace chooser. For first-time setup, create a workspace and onboard a tenant via the wizard.
  10. System console: Navigate to /system — requires platform_users record with platform guard.