# TenantPilot Constitution ## Core Principles ### Inventory-first, Snapshots-second - All modules MUST operate primarily on Inventory as “last observed” state. - Inventory is the source of truth for what TenantPilot last observed; Microsoft Intune remains the external truth. - Snapshots/Backups MUST be explicit actions (manual or scheduled) and MUST remain immutable. ### Read/Write Separation by Default - Analysis, reporting, and monitoring features MUST be read-only by default. - Any write/change function (restore, remediation, promotion) MUST include preview/dry-run, explicit confirmation, audit logging, and tests. - High-risk policy types default to `preview-only` restore unless explicitly enabled by a feature spec + tests. ### Single Contract Path to Graph - All Microsoft Graph calls MUST go through `GraphClientInterface`. - Object types and endpoints MUST be modeled first in the contract registry (`config/graph_contracts.php`). - Feature code MUST NOT hardcode “quick endpoints” or bypass contracts. - Unknown/missing policy types MUST fail safe (preview-only / no Graph calls) rather than guessing endpoints. ### Deterministic Capabilities - Backup/restore/risk/support flags MUST be derived deterministically from config/contracts via a Capabilities Resolver. - The resolver output MUST be programmatically testable (snapshot/golden tests) so config changes cannot silently break behavior. ### Tenant Isolation is Non-negotiable - Every read/write MUST be tenant-scoped. - Cross-tenant views (MSP/Platform) MUST be explicit, access-checked, and aggregation-based (no ID-based shortcuts). - Prefer least-privilege roles/scopes; surface warnings when higher privileges are selected. ### Automation must be Idempotent & Observable - Scheduled/queued operations MUST use locks + idempotency (no duplicates). - Long-running operations MUST create run records with status, counts, and stable error codes. - Graph throttling and transient failures MUST be handled with backoff + jitter (e.g., 429/503). - Failures MUST be visible and actionable (no silent best-effort). ### Data Minimization & Safe Logging - Inventory MUST store only metadata + whitelisted `meta_jsonb`. - Payload-heavy content belongs in immutable snapshots/backup storage, not Inventory. - Logs MUST not contain secrets/tokens; monitoring MUST rely on run records + error codes (not log parsing). ### Spec-First Workflow - For any feature that changes runtime behavior, include or update `specs/-/` with `spec.md`, `plan.md`, `tasks.md`, and `checklists/requirements.md`. - New work branches from `dev` using `feat/-` (spec + code in the same PR). ## Quality Gates - Changes MUST be programmatically tested (Pest) and run via targeted `php artisan test ...`. - Run `./vendor/bin/pint --dirty` before finalizing. ## Governance ### Scope & Compliance - This constitution applies across the repo. Feature specs may add stricter constraints but not weaker ones. - Restore semantics changes require: spec update, checklist update (if applicable), and tests proving safety. ### Amendment Procedure - Propose changes as a PR that updates `.specify/memory/constitution.md`. - The PR MUST include a short rationale and list of impacted templates/specs. - Amendments MUST update **Last Amended** date. ### Versioning Policy (SemVer) - **PATCH**: clarifications/typos/non-semantic refinements. - **MINOR**: new principle/section or materially expanded guidance. - **MAJOR**: removing/redefining principles in a backward-incompatible way. **Version**: 1.1.0 | **Ratified**: 2026-01-03 | **Last Amended**: 2026-01-07