TenantAtlas/.specify/memory/constitution.md
ahmido 3a3de045ba docs: enforce RBAC constitution gates in spec templates (#78)
## Summary
<!-- Kurz: Was ändert sich und warum? -->

## Spec-Driven Development (SDD)
- [ ] Es gibt eine Spec unter `specs/<NNN>-<feature>/`
- [ ] Enthaltene Dateien: `plan.md`, `tasks.md`, `spec.md`
- [ ] Spec beschreibt Verhalten/Acceptance Criteria (nicht nur Implementation)
- [ ] Wenn sich Anforderungen während der Umsetzung geändert haben: Spec/Plan/Tasks wurden aktualisiert

## Implementation
- [ ] Implementierung entspricht der Spec
- [ ] Edge cases / Fehlerfälle berücksichtigt
- [ ] Keine unbeabsichtigten Änderungen außerhalb des Scopes

## Tests
- [ ] Tests ergänzt/aktualisiert (Pest/PHPUnit)
- [ ] Relevante Tests lokal ausgeführt (`./vendor/bin/sail artisan test` oder `php artisan test`)

## Migration / Config / Ops (falls relevant)
- [ ] Migration(en) enthalten und getestet
- [ ] Rollback bedacht (rückwärts kompatibel, sichere Migration)
- [ ] Neue Env Vars dokumentiert (`.env.example` / Doku)
- [ ] Queue/cron/storage Auswirkungen geprüft

## UI (Filament/Livewire) (falls relevant)
- [ ] UI-Flows geprüft
- [ ] Screenshots/Notizen hinzugefügt

## Notes
<!-- Links, Screenshots, Follow-ups, offene Punkte -->

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Reviewed-on: #78
2026-01-27 22:09:56 +00:00

9.5 KiB

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.
  • A non-member attempting to access a tenant route MUST be deny-as-not-found (404).

RBAC Standard (RBAC-001)

RBAC-001 Two Planes

  • The platform MUST maintain two strictly separated authorization planes:
    • Tenant plane (/admin/t/{tenant}): authenticated Entra users (users), authorization is tenant-scoped.
    • Platform plane (/system): authenticated platform users (platform_users), authorization is platform-scoped.
  • Cross-plane access MUST be deny-as-not-found (404) (not 403) to avoid route enumeration.

RBAC-002 Capabilities-first Authorization

  • Feature code MUST NOT check raw roles directly (e.g. string role comparisons).
  • Feature code MUST check capabilities via Gates/Policies only.
  • A canonical capability registry MUST exist as the single source of truth (e.g. TenantCapabilities / PlatformCapabilities).
  • Role → capability mapping MUST reference only registry entries.

RBAC-003 Least Privilege Role Semantics

  • Tenant roles MUST follow least-privilege semantics:
    • Readonly: view-only; MUST NOT start operations and MUST NOT mutate data.
    • Operator: MAY start allowed tenant operations; MUST NOT manage credentials, settings, members, or perform destructive actions.
    • Manager: MAY manage tenant configuration and start operations; MUST NOT manage tenant memberships (Owner-only).
    • Owner: MAY manage memberships and all tenant configuration; Owner-only “danger zone” actions MUST remain Owner-only.

RBAC-004 UI is not Security

  • Hiding UI elements is NOT sufficient.
  • Every mutation endpoint and action MUST enforce authorization server-side (Policy/Gate).

RBAC-005 Destructive Actions Gate

  • All destructive actions (delete / force delete / irreversible operations) MUST:
    • require an explicit confirmation (e.g., requiresConfirmation() or equivalent),
    • be protected by a Policy/Gate,
    • have at least one regression test asserting the action is forbidden for non-authorized roles.

RBAC-006 Membership Safety Rule

  • The system MUST prevent removing or demoting the last remaining Owner of a tenant.

RBAC-007 Tenant Isolation

  • All tenant-plane queries MUST be tenant-scoped.
  • A non-member attempting to access a tenant route MUST be deny-as-not-found (404).

RBAC-008 Auditing

  • All access-control relevant changes MUST write AuditLog entries with stable action IDs, including:
    • membership add / role change / remove
    • provider credential rotation / connection disable
    • break-glass enter / exit / expire (platform plane)
  • AuditLog entries MUST be redacted (no secrets/tokens, minimal identity fields).

RBAC-009 Testability Gate

  • Any new feature that introduces or changes authorization MUST include:
    • at least one positive test (authorized user can do it),
    • at least one negative test (unauthorized user cannot do it),
    • and MUST NOT introduce role-string checks outside the central mapping/registry.

Operations / Run Observability Standard

  • Every long-running or operationally relevant action MUST be observable, deduplicated, and auditable via Monitoring → Operations.
  • An action MUST create/reuse a canonical OperationRun and execute asynchronously when any of the following applies:
    1. It can take > 2 seconds under normal conditions.
    2. It performs remote/external calls (e.g., Microsoft Graph).
    3. It is queued or scheduled.
    4. It is operationally relevant for troubleshooting/audit (“what ran, who started it, did it succeed, what failed?”).
  • Actions that are DB-only and typically complete in < 2 seconds MAY skip OperationRun.
  • OPS-EX-AUTH-001 — Auth Handshake Exception:
    • OIDC/SAML login handshakes MAY perform synchronous outbound HTTP (e.g., token exchange) without an OperationRun.
    • Rationale: interactive, session-critical, and not a tenant-operational “background job”.
    • Guardrail: outbound HTTP for auth handshakes is allowed only on /auth/* endpoints and MUST NOT occur on Monitoring/Operations pages.
  • If an action is security-relevant or affects operational behavior (e.g., “Ignore policy”), it MUST write an AuditLog entry including actor, tenant, action, target, before/after, and timestamp.
  • The OperationRun record is the canonical source of truth for Monitoring (status, timestamps, counts, failures), even if implemented by multiple jobs/steps (“umbrella run”).
  • “Single-row” runs MUST still use consistent counters (e.g., total=1, processed=0|1) and outcome derived from success/failure.
  • Monitoring pages MUST be DB-only at render time (no external calls).
  • Start surfaces MUST NOT perform remote work inline; they only: authorize, create/reuse run (dedupe), enqueue work, confirm + “View run”.
  • Active-run dedupe MUST be enforced at DB level (partial unique index/constraint for active states).
  • Failures MUST be stored as stable reason codes + sanitized messages; never persist secrets/tokens/PII/raw payload dumps in failures or notifications.
  • Graph calls are allowed only via explicit user interaction and only when delegated auth is present; never as a render side-effect (restore group mapping is intentionally DB-only).
  • Monitoring → Operations is reserved for OperationRun-tracked operations.
  • Scheduled/queued operations MUST use locks + idempotency (no duplicates).
  • Graph throttling and transient failures MUST be handled with backoff + jitter (e.g., 429/503).

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).

Badge Semantics Are Centralized (BADGE-001)

  • Status-like badges (status/outcome/severity/risk/availability/boolean signals) MUST render via BadgeCatalog / BadgeRenderer.
  • Filament resources/pages/widgets/views MUST NOT introduce ad-hoc status-like badge mappings (use a BadgeDomain instead).
  • Introducing or changing a status-like value MUST include updating the relevant badge mapper and adding/updating tests for the mapping.
  • Tag/category chips (e.g., type/platform/environment) are not status-like and are not governed by BADGE-001.

Spec-First Workflow

  • For any feature that changes runtime behavior, include or update specs/<NNN>-<slug>/ with spec.md, plan.md, tasks.md, and checklists/requirements.md.
  • New work branches from dev using feat/<NNN>-<slug> (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.5.0 | Ratified: 2026-01-03 | Last Amended: 2026-01-27