<!--
Sync Impact Report

- Version change: 2.12.0 -> 2.13.0
- Modified principles:
  - Expanded Filament Native First / No Ad-hoc Styling (UI-FIL-001)
    so custom Filament UI must follow the canonical TenantPilot
    enterprise UI standard, must not introduce ad-hoc styling for
    cards, buttons, hovers, badges, icons, progress bars, empty states,
    or interactive rows, and may only show interactive affordance when
    a repo-real route/action and permitted capability exist
- Added sections: None
- Removed sections: None
- Templates requiring updates:
  - .specify/templates/spec-template.md: require canonical UI-standard
    compliance, no ad-hoc custom styling, and repo-real affordance
    disclosure ✅
  - .specify/templates/plan-template.md: add UI-FIL-001 checks for the
    canonical UI standard and affordance honesty ✅
  - .specify/templates/tasks-template.md: add implementation tasks for
    no ad-hoc styling and repo-real interactive affordances ✅
  - .specify/templates/checklist-template.md: add explicit custom UI
    standard and affordance review check ✅
  - docs/product/principles.md: align the high-level product rule with
    the canonical UI standard ✅
  - docs/product/standards/filament-native-enterprise-ui.md: align the
    compact standard with the canonical UI source ✅
  - docs/product/standards/README.md: index the canonical UI-standard
    document ✅
  - docs/HANDOVER.md: refresh the Filament standards summary ✅
  - docs/ui/tenantpilot-enterprise-ui-standards.md: fix the
    constitution-reference path to the canonical file ✅
- Commands checked:
  - N/A `.specify/templates/commands/*.md` directory is not present
- Follow-up TODOs: None
-->

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

### Proportionality First (PROP-001)
- New structure, layering, persistence, or semantic machinery MUST be justified by current release truth, current operator workflow, and a concrete reason a narrower implementation is insufficient.
- Code MUST NOT become more generic, more layered, or more persistent than the current product actually needs.
- Reviews MUST reject speculative generalization framed only as future flexibility.

### No Premature Abstraction (ABSTR-001)
- New factories, registries, resolvers, strategy systems, interfaces, extension-point frameworks, type registries, or orchestration pipelines MUST NOT be introduced before at least two real concrete cases require them.
- Test convenience alone is not sufficient justification for a new abstraction.
- Narrow abstractions are allowed when required for security, tenant isolation, auditability, compliance evidence, or queue/job execution correctness.

### First Provider Is Not Platform Core (PROV-001)
- Microsoft is the current first provider, not the platform core.
- Shared platform-owned contracts, taxonomies, identifiers, compare semantics, and operator vocabulary MUST NOT silently become Microsoft-shaped truth just because Microsoft is the only provider today.
- Shared platform-owned boundaries SHOULD prefer neutral core terms such as `provider`, `connection`, `target scope`, `governed subject`, and `operation` unless the feature is intentionally provider-owned and explicitly bounded.
- Shared core terms at shared boundaries (PROV-002): if a boundary is reused across multiple domains, features, or workflows, the default is neutral platform language rather than provider-specific labels or semantics.
- No accidental deepening of provider coupling (PROV-003): a feature MAY retain provider-specific semantics at a provider-owned seam, but it MUST NOT spread those semantics deeper into platform-core contracts, shared persistence truth, shared taxonomies, or shared UI language without proving that the narrower current-release truth genuinely requires it.
- Shared-boundary review is mandatory (PROV-004): when a feature touches a shared provider/platform seam, the spec, plan, and review MUST state whether the seam is provider-owned or platform-core, what provider-specific semantics remain, and why that choice is the narrowest correct implementation now.
- Prefer bounded extraction over premature generalization (PROV-005): if an existing hotspot is too Microsoft-specific, the default remedy is a bounded normalization or extraction of that hotspot, not a speculative multi-provider framework with unused extension points.

### No New Persisted Truth Without Source-of-Truth Need (PERSIST-001)
- New tables, persisted entities, or stored artifacts MUST represent real product truth that survives independently of the originating request, run, or view.
- Persisted storage is justified only when at least one of these is true: it is a source of truth, has an independent lifecycle, must be audited independently, must outlive its originating run/request, is required for permissions/routing/compliance evidence, or is required for stable operator workflows over time.
- Convenience projections, UI helpers, speculative artifacts, derived summaries, and temporary semantic wrappers MUST remain derived unless current-release operator workflows require independent persistence.
- Release 2/3 entities MUST NOT be fully built in Release 1 unless they are foundational and already exercised by the shipped workflow.

### No New State Without Behavioral Consequence (STATE-001)
- New states, statuses, reason codes, lifecycle labels, and semantic categories MUST change operator action, workflow routing, permission or policy enforcement, lifecycle behavior, persistence truth, audit responsibility, retention behavior, or retry/failure handling.
- Presentation-only distinctions MUST remain derived labels rather than persisted domain state.
- Reason code families MUST NOT expand unless each added value has a distinct system or operator consequence.

### UI Semantics Must Not Become Their Own Framework (UI-SEM-001)
- Badges, explanation text, trust/confidence labels, detail cards, and status summaries MUST remain lightweight presentation helpers unless they are proven product contracts.
- New UI semantics MUST NOT require mandatory presenter, badge, explanation, taxonomy, or multi-step interpretation pipelines by default.
- Direct mapping from canonical domain truth to UI is preferred over intermediate semantic superstructures.
- Presentation helpers SHOULD remain optional adapters, not mandatory architecture.

### Shared Pattern First For Cross-Cutting Interaction Classes (XCUT-001)
- Cross-cutting interaction classes such as notifications, status messaging, action links, header actions, dashboard signals/cards, navigation entry points, alerts, evidence/report viewers, and similar operator-facing infrastructure MUST first attach to an existing shared contract, presenter, builder, renderer, or other shared path when one already exists.
- New local or domain-specific implementations for an existing interaction class are allowed only when the current shared path is demonstrably insufficient for current-release truth.
- The active spec MUST name the shared path being reused or explicitly record the deviation, why the existing path is insufficient, what consistency must still be preserved, and what ownership or spread-control cost the deviation creates.
- The same interaction class MUST NOT develop parallel operator-facing UX languages for title/body/action structure, status semantics, action-label patterns, or deep-link behavior unless the deviation is explicit and justified.
- Reviews MUST treat undocumented bypass of an existing shared path as drift and block merge until the feature converges on the shared path or records a bounded exception.
- If the drift is discovered only after a feature is already implemented, the remedy is NOT to rewrite historical closed specs retroactively by default; instead the active work MUST record the issue as `document-in-feature` or escalate it as `follow-up-spec`, depending on whether the drift is contained or structural.

### V1 Prefers Explicit Narrow Implementations (V1-EXP-001)
- For V1 and early product maturity, direct implementation, local mapping, explicit per-domain logic, small focused helpers, derived read models, and minimal UI adapters are preferred.
- Generic platform engines, meta-frameworks, universal resolver systems, workflow frameworks, and broad semantic taxonomies are disfavored until real variance proves them necessary.
- The burden of proof is always on the broader abstraction.

### One Truth, Few Layers (LAYER-001)
- A single domain truth MUST NOT be redundantly modeled across model fields, service result objects, presenters, UI summaries, explanation builders, badge taxonomies, run context wrappers, and persisted mirror entities without clear necessity.
- Prefer one canonical truth with thin adapters.
- Any new layer MUST replace an existing layer or prove why the existing layer cannot serve the need.
- Additive semantic layering is discouraged; absorption is preferred over accumulation.

### Spec Discipline Over Slice Proliferation (SPEC-DISC-001)
- Related semantic, taxonomy, and presentation-contract changes SHOULD be grouped into one coherent spec instead of many micro-specs that each add classes, enums, DTOs, and tests.
- Every spec MUST explicitly state whether it introduces a new source of truth, persisted entity, abstraction, state, or cross-cutting framework.
- If the answer is yes, the spec MUST explain why the addition is necessary now.

### Tests Must Protect Business Truth (TEST-TRUTH-001)
- Testing is mandatory, but test growth MUST follow business truth rather than indirection created for its own sake.
- Tests MUST prioritize domain behavior, permissions, isolation, lifecycle correctness, and operator-critical outcomes.
- Large dedicated test surfaces for thin presentation indirection SHOULD be avoided.
- If a pattern creates more test burden than product certainty, the pattern SHOULD be simplified.

### Test Suite Governance Must Live In The Delivery Workflow (TEST-GOV-001)
- Test-suite governance is a standing workflow rule, not an occasional cleanup project.
- Every spec or implementation change that changes runtime behavior, tests, lane mix, or shared test infrastructure MUST state test impact explicitly: affected validation lane(s), actual test purpose classification (`Unit`, `Feature`, `Heavy-Governance`, `Browser`), any new or broader test family, fixture/helper/factory/seed/context cost change, and any budget, baseline, or trend follow-up.
- Docs-only, template-only, or otherwise no-runtime-impact work MAY answer the test-governance prompts with concise `N/A` or `none`, but MUST still make the absence of runtime or suite impact explicit.
- Test classification MUST follow the proving purpose of the change rather than directory names, filenames, or convenience. Fast or narrow lanes MUST NOT silently absorb discovery, surface, workflow, or browser cost that belongs in heavier governance lanes.
- Minimal fixtures and minimal infrastructure are the default. Database, Livewire, Filament, provider setup, workspace or membership context, session state, capability context, and similar expensive dependencies MUST be used only when the asserted behavior requires them.
- Heavy families MUST remain explicit in naming, lane assignment, and review rationale. New or expanded heavy-governance, discovery, surface, broad workflow, or browser families MUST NOT appear accidentally through helper drift, copied setup, or folder placement alone.
- Shared helpers, factories, seeds, and support layers MUST keep expensive context opt-in. Provider, workspace, membership, capability, session, or similar full-context defaults MUST NOT become implicit norms.
- Lane budgets, baselines, and trend reports are engineering constraints. Changes that materially worsen runtime, shift lane semantics, or create heavy cost centers MUST be validated, documented, and escalated when the impact exceeds ordinary feature-local upkeep.
- Reviews MUST stop test drift before merge. Reviewers MUST verify lane fit, test breadth, fixture cost, heavy-family risk, and runtime impact, and MUST treat unnecessary breadth, wrong classification, or hidden cost as merge blockers rather than later CI cleanup.
- Review checklists MUST end with one explicit outcome: `keep`, `split`, `document-in-feature`, `follow-up-spec`, or `reject-or-split`, so the decision about suite-cost risk is attributable instead of implied.
- New governance cost centers, including new heavy families, new browser coverage, material lane-cost shifts, revived expensive defaults, or budget/baseline-relevant regressions, MUST be documented explicitly. Contained feature-local cases MAY be `document-in-feature`; structural or recurring cases MUST escalate to `follow-up-spec`; unjustified scope or hidden cost MUST resolve as `reject-or-split`.
- These rules MUST stay visible in the spec, plan, task, and review routine. Test governance MUST NOT live only in CI output, wrapper scripts, or tribal knowledge.

### Enterprise Complexity Is Allowed Only Where Risk Demands It (RISK-COMP-001)
- Heavier architecture is explicitly legitimate for workspace or tenant isolation, RBAC and policy enforcement, auditability, immutable history and snapshot truth, queue/job execution legitimacy, provider credential safety, retention/compliance evidence, and operator-critical lifecycle correctness.
- Badge systems, explanation builders, trust/confidence overlays, presentation taxonomies, generic provider frameworks without real provider variance, speculative export/report/review infrastructure, UI meta-governance frameworks, and derived helper entities promoted into persisted truth are high-risk overproduction zones and require extra restraint.

### Mandatory Bloat Check for New Specs (BLOAT-001)
- Any spec that introduces a new enum or status family, DTO/envelope/presenter layer, persisted entity or table, interface/contract/registry/resolver, cross-domain UI framework, or taxonomy/classification system MUST include a proportionality review.
- That review MUST answer:
  1. What current operator problem does this solve?
  2. Why is existing structure insufficient?
  3. Why is this the narrowest correct implementation?
  4. What ownership cost does this create?
  5. What alternative was intentionally rejected?
  6. Is this current-release truth or future-release preparation?
- Specs that cannot answer these questions clearly MUST NOT merge.

### Spec Candidate Gate (SPEC-GATE-001)
- Every new spec candidate MUST pass the Spec Approval Rubric (`.specify/memory/spec-approval-rubric.md`) before progressing beyond Draft status.
- The spec MUST include a filled-out "Spec Candidate Check" section answering the 5 mandatory questions (operator workflow, trust/safety, smallest version, permanent complexity, why now).
- The spec MUST be classified into exactly one approval class: Core Enterprise, Workflow Compression, Cleanup, or Defer.
- The spec MUST include a scored evaluation (6 dimensions, 0–2 each). Specs scoring below 7/12 MUST NOT be approved without explicit scope reduction.
- If two or more red flags from the rubric are triggered, the spec MUST include an explicit defense justifying why it should proceed.
- Specs classified as "Defer" or scoring 0–3 MUST NOT be implemented.
- This gate applies to all spec-creating agents (speckit.specify, speckit.plan) and manual spec creation alike.

### Default Bias (BIAS-001)
- Default codebase bias is: derive before persist, map before frameworkize, localize before generalize, simplify before extend, replace before layer, explicit before generic, and present directly before interpreting recursively.

### Pre-Production Lean Doctrine (LEAN-001)

This product has no production deployment, no live customer data, no shared staging with migration-relevant state, and no external API contract consumers.

#### Data and schema
- Old data shapes, column names, enum values, and operation types MAY be replaced in place.
- Migration shims, dual-write logic, and fallback readers MUST NOT be created unless a spec explicitly requires compatibility behavior.

#### Terminology and types
- Renamed or unified operation types, reason codes, and status values MUST replace the old value everywhere (code, config, tests, fixtures, seed data).
- Legacy aliases kept "just in case" are forbidden.

#### Codebase hygiene
- Dead constants, dead enum cases, orphan config keys, and test fixtures that reference replaced shapes MUST be removed in the same PR that introduces the replacement.
- "Old runs / old rows don't matter" is the standing assumption until the product ships.

#### AI-agent rule
- Before adding aliases, fallback readers, dual-write logic, migration shims, or legacy fixtures, agents MUST verify:
  1. Do live production data exist?
  2. Is shared staging migration-relevant?
  3. Does an external contract depend on the old shape?
  4. Does the spec explicitly require compatibility behavior?
- If all answers are no, replace the old shape and remove the compatibility path.

#### Review rule
- Any PR that introduces a new legacy alias, compatibility shim, or historical fixture without answering the four questions above is a merge blocker.

#### Exit condition
- LEAN-001 expires when the first production deployment occurs.
- At that point, the constitution MUST be amended to define the real migration and compatibility policy.

### Workspace Isolation is Non-negotiable
- Workspace membership is an isolation boundary. If the actor is not entitled to the workspace scope, the system MUST respond as
  deny-as-not-found (404).
- Workspace is the primary session context. Tenant-scoped routes/resources MUST require an established workspace context.
- Workspace context switching is separate from Filament Tenancy (Managed Tenant switching).

### Tenant Isolation is Non-negotiable
- Every tenant-plane read/write MUST be tenant-scoped.
- Cross-tenant views (MSP/Platform) MUST be explicit, access-checked, and aggregation-based (no ID-based shortcuts).
- Tenantless canonical views (e.g., Monitoring/Operations) MUST enforce tenant entitlement before revealing records.
- Prefer least-privilege roles/scopes; surface warnings when higher privileges are selected.
- Tenant membership is an isolation boundary. If the actor is not entitled to the tenant scope, the system MUST respond as
  deny-as-not-found (404).

Scope & Ownership Clarification (SCOPE-001)

- The system MUST enforce a strict ownership model:
  - Workspace-owned objects define standards, templates, and global configuration (e.g., Baseline Profiles, Notification Targets, Alert Routing Rules, Framework/Control catalogs).
  - Tenant-owned objects represent observed state, evidence, and operational artifacts for a specific tenant (e.g., Inventory, Backups/Snapshots, OperationRuns for tenant operations, Drift/Findings, Exceptions/Risk Acceptance, EvidenceItems, StoredReports/Exports).
- Workspace-owned objects MUST NOT directly embed or persist tenant-owned records (no “copying tenant data into templates”).
- Tenant-owned objects MUST always be bound to an established workspace + tenant scope at authorization time.

Database convention:

- Tenant-owned tables MUST include workspace_id and tenant_id as NOT NULL.
- Workspace-owned tables MUST include workspace_id and MUST NOT include tenant_id.
- Exception: OperationRun MAY have tenant_id nullable to support canonical workspace-context monitoring views; however, revealing any tenant-bound runs still MUST enforce entitlement checks to the referenced tenant scope.
- Exception: AlertDelivery MAY have tenant_id nullable for workspace-scoped, non-tenant-operational artifacts (e.g., `event_type=alerts.test`). Tenant-bound delivery records still MUST enforce tenant entitlement checks, and tenantless delivery rows MUST NOT contain tenant-specific data.
- Exception: `managed_tenant_onboarding_sessions` MAY keep `tenant_id` nullable as a workspace-scoped workflow-coordination record. It begins before tenant identification, may later reference a tenant for authorization continuity and resume semantics, and MUST always enforce workspace entitlement plus tenant entitlement once a tenant reference is attached. This exception is specific to onboarding draft workflow state and does not create a general precedent for workspace-owned domain records.

### RBAC & UI Enforcement Standards (RBAC-UX)

RBAC Context — Planes, Roles, and Auditability
- The platform MUST maintain two strictly separated authorization planes:
  - Tenant/Admin plane (`/admin`): authenticated Entra users (`users`).
  - Tenant-context routes (`/admin/t/{tenant}/...`) are tenant-scoped.
  - Workspace-context canonical routes (`/admin/...`, e.g. Monitoring/Operations) are tenantless by URL but MUST still enforce workspace + tenant entitlement before revealing tenant-owned records.
  - 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.
- Tenant role semantics MUST remain least-privilege:
  - 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.
- The system MUST prevent removing or demoting the last remaining Owner of a tenant.
- All access-control relevant changes MUST write `AuditLog` entries with stable action IDs, and MUST be redacted (no secrets).

RBAC-UX-001 — Server-side is the source of truth
- UI visibility / disabled state is never a security boundary.
- Every mutating action (create/update/delete/restore/archive/force-delete), every operation start, and every credential/
  config change MUST enforce authorization server-side via `Gate::authorize(...)` or a Policy method.
- Any missing server-side authorization is a P0 security bug.

RBAC-UX-002 — Deny-as-not-found for non-members
- Tenant and workspace membership (and plane membership) are isolation boundaries.
- If the current actor is not a member of the current workspace OR the current tenant (or otherwise not entitled to the
  workspace/tenant scope), the system MUST respond as 404 (deny-as-not-found) for tenant-scoped routes/actions/resources.
- This applies to Filament resources/pages under tenant routing (`/admin/t/{tenant}/...`), Global Search results, and all
  action endpoints (Livewire calls included).

RBAC-UX-003 — Capability denial is 403 (after membership is established)
- Within an established workspace + tenant scope, missing permissions are authorization failures.
- If the actor is a workspace + tenant member, but lacks the required capability for an action, the server MUST fail with 403.
- The UI may render disabled actions, but the server MUST still enforce 403 on execution.

RBAC-UX-004 — Visible vs disabled UX rule
- For tenant members: actions SHOULD be visible but disabled when capability is missing.
- Disabled actions MUST provide helper text explaining the missing permission.
- For non-members: actions MUST behave as not found (404) and SHOULD NOT leak resource existence.
- Exception: highly sensitive controls (e.g., credential rotation) MAY be hidden even for members without permission.

RBAC-UX-005 — Destructive confirmation standard
- All destructive-like actions MUST require confirmation.
- Delete/force-delete/archive/restore/remove membership/role downgrade/credential rotation/break-glass enter/exit MUST use
  `->requiresConfirmation()` and SHOULD include clear warning text.
- Confirmation is UX only; authorization still MUST be server-side.

RBAC-UX-006 — Capability registry is canonical
- Capabilities MUST be centrally defined in a single canonical registry (constants/enum).
- Feature code MUST reference capabilities only via the registry (no raw string literals).
- Role → capability mapping MUST reference only registry entries.
- CI MUST fail if unknown/unregistered capabilities are used.

RBAC-UX-007 — Global search must be tenant-safe
- Global search MUST be context-safe (workspace-context vs tenant-context).
- Non-members MUST never learn about resources in other tenants (no results, no hints).
- If a result exists but is not accessible, it MUST be treated as not found (404 semantics).
- In workspace-context (no active tenant selected), Global Search MUST NOT return tenant-owned results.
- It MAY search workspace-owned objects only (e.g., Tenants list entries, Baseline Profiles, Alert Rules/Targets, workspace settings).
- If tenant-context is active, Global Search MUST be scoped to the current tenant only (existing rule remains).

RBAC-UX-008 — Regression guards are mandatory
- The repo MUST include RBAC regression tests asserting at least:
  - Readonly cannot mutate or start operations.
  - Operator can run allowed operations but cannot manage configuration.
  - Manager/Owner behave according to the role matrix.
- The repo SHOULD include an automated “no ad-hoc authorization” guard that blocks new status/permission mappings sprinkled
  across `app/Filament/**`, pushing patterns into central helpers.

### 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 and MUST NOT compose OperationRun start UX locally; they only:
  authorize, create/reuse run (dedupe), enqueue work, and hand queued/start-state feedback to the shared
  OperationRun Start UX Contract.

### OperationRun Start UX Contract (OPS-UX-START-001)

- OperationRun UX MUST be contract-driven, not surface-driven.
- Any feature that creates, queues, deduplicates, resumes, blocks, completes, or links to an `OperationRun` MUST use
  the central OperationRun Start UX Contract.
- Filament Pages, Resources, Widgets, Livewire Components, Actions, and Services MUST NOT independently compose
  OperationRun start UX from local pieces.
- The shared OperationRun UX layer MUST own:
  - local start notification / toast
  - `Open operation` / `View run` link
  - artifact link such as `View snapshot`, `View pack`, or `View restore`
  - run-enqueued browser event
  - queued DB-notification decision
  - dedupe / already-available / already-running messaging
  - blocked / failed-to-start messaging
  - tenant/workspace-safe operation URL resolution
- Feature surfaces MAY initiate `OperationRun`s, but they MUST NOT define their own OperationRun UX semantics.
- `OperationRun` lifecycle state remains the canonical execution truth.
- Queued DB notifications MUST remain explicit opt-in unless the active spec defines a different policy.
- Terminal `OperationRun` notifications MUST be emitted through the central OperationRun lifecycle mechanism.
- Any exception MUST include:
  1. an explicit spec decision,
  2. a documented architecture note,
  3. a test or guard-test exception with rationale,
  4. a follow-up migration decision if the exception is temporary.
- New OperationRun-starting features MUST include an `OperationRun UX Impact` section in the active spec or plan.

### Operations UX — 3-Surface Feedback (OPS-UX-055) (NON-NEGOTIABLE)

If a feature creates/reuses `OperationRun`, its default feedback contract is exactly three surfaces.
Queued DB notifications are forbidden by default and MAY exist only when the active spec explicitly opts into them
through the OperationRun Start UX Contract:

1) Toast (intent only / queued-only)
- A toast MAY be shown only when the run is accepted/queued (intent feedback).
- The toast MUST use `OperationUxPresenter::queuedToast($operationType)->send()`.
- Feature code MUST NOT craft ad-hoc operation toasts.
- A dedicated dedupe message MUST use the presenter (e.g., `alreadyQueuedToast(...)`), not `Notification::make()`.
- Queued toast copy, action links, artifact links, start-state browser events, and dedupe/start-failure messaging MUST be
  produced by the shared OperationRun Start UX Contract, not by local surface code.

2) Progress (active awareness only)
- Live progress MUST exist only in:
  - the global active-ops widget, and
  - Monitoring → Operation Run Detail.
- These surfaces MUST show only active runs (`queued|running`) and MUST never show terminal runs.
- Running DB notifications are forbidden.
- Determinate progress is allowed ONLY when `summary_counts.total` and `summary_counts.processed` are valid numeric values.
- Determinate progress MUST be clamped to 0–100. Otherwise render indeterminate + elapsed time.
- The widget MUST NOT show percentage text (optional `processed/total` is allowed).

3) Terminal DB Notification (audit outcome only)
- Each run MUST emit exactly one persistent terminal DB notification when it becomes terminal.
- Delivery MUST be initiator-only (no tenant-wide fan-out).
- Completion notifications MUST be `OperationRunCompleted` only.
- Feature code MUST NOT send custom completion DB notifications for operations (no `sendToDatabase()` for completion/abort).

Canonical navigation:
- All “View run” links MUST use the canonical helper and MUST point to Monitoring → Operations → Run Detail.

### OperationRun lifecycle is service-owned (OPS-UX-LC-001)

Any change to `OperationRun.status` or `OperationRun.outcome` MUST go through `OperationRunService` (canonical transition method).
This is the only allowed path because it enforces normalization, summary sanitization, idempotency, and terminal notification emission.

Forbidden outside `OperationRunService`:
- `$operationRun->update(['status' => ...])` / `$operationRun->update(['outcome' => ...])`
- `$operationRun->status = ...` / `$operationRun->outcome = ...`
- Query-based updates that transition `status`/`outcome`

Allowed outside the service:
- Updates to `context`, `message`, `reason_code` that do not change `status`/`outcome`.

### Summary counts contract (OPS-UX-SUM-001)

- `operation_runs.summary_counts` is the canonical metrics source for Ops-UX.
- All keys MUST come from `OperationSummaryKeys::all()` (single source of truth).
- Values MUST be flat numeric-only; no nested objects/arrays; no free-text.
- Producers MUST NOT introduce new keys without:
  1) updating `OperationSummaryKeys::all()`,
  2) updating the spec canonical list,
  3) adding/adjusting tests.

### Ops-UX regression guards are mandatory (OPS-UX-GUARD-001)

The repo MUST include automated guards (Pest) that fail CI if:
- any direct `OperationRun` status/outcome transition occurs outside `OperationRunService`,
- feature code bypasses the central OperationRun Start UX Contract for queued/start-state operation UX where the repo's
  guardable patterns can detect it,
- feature code emits queued DB notifications for operations without explicit spec-driven opt-in through the shared
  OperationRun UX layer,
- jobs emit DB notifications for operation completion/abort (`OperationRunCompleted` is the single terminal notification),
- deprecated legacy operation notification classes are referenced again.

These guards MUST fail with actionable output (file + snippet).

### Scheduled/system runs (OPS-UX-SYS-001)

- If a run has no initiator user, no terminal DB notification is emitted (initiator-only policy).
- Outcomes remain auditable via Monitoring → Operations / Run Detail.
- Any tenant-wide alerting MUST go through the Alerts system (not `OperationRun` notifications).
- 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).

### Operator-Facing UI/UX Constitution v1 (UI-CONST-001)

Purpose and scope
- This section governs operator-facing admin UI semantics across TenantPilot / TenantAtlas.
- It defines decision-first prominence roles, allowed surface types,
  allowed interaction models, primary/secondary/destructive action
  hierarchy, list/detail/queue semantics, scope and context signals,
  canonical navigation and naming rules, visibility of critical
  operational truth, scanability and density rules, exception handling,
  and review and enforcement requirements.
- It does not govern branding, colors, typography, spacing tokens, marketing or landing pages, implementation details without UX effect, purely cosmetic copy changes, or backend architecture except where backend design would create false UI mental models.
- This section is governance, not a style guide. Its purpose is to prevent ambiguity, operator risk, and UI drift before they spread through the product.

#### Decision-First Operating Model & Progressive Disclosure (DECIDE-001)

Goal: TenantPilot is primarily a governance and decision platform, not
a browser for internal technical detail objects. This section governs
surface prominence and default information depth. It is orthogonal to
UI-SURF-001 and ACTSURF-001: every operator-facing surface MUST declare
both its interaction model and its decision-role prominence.

##### Surface prominence roles

- Every operator-facing surface MUST declare exactly one decision-role
  prominence:
  - Primary Decision Surface
  - Secondary Context Surface
  - Tertiary Evidence / Diagnostics Surface
- Decision-role prominence is separate from action-surface class and
  detailed surface type.
- Prominence determines what deserves top-level navigation, default
  emphasis, and default-visible information depth.

##### Primary surfaces are for human decisions

- Primary Decision Surfaces MUST support a clear human-in-the-loop
  moment such as attention prioritization, approval, risk acceptance or
  rejection, drift / findings / exception triage, review completion,
  evaluation of blocked or failed automations, or execution /
  escalation of the next governance action.
- A prominent surface MUST NOT exist primarily to display internal
  model objects, raw data, diagnostics, or technical object hubs
  without clear operator value.
- Every proposed primary surface MUST answer: what concrete decision or
  operator action does this surface support?

##### Detail surfaces are evidence surfaces

- OperationRun detail, evidence detail, policy version detail, audit
  log detail, JSON / payload / diff views, and deep diagnostic contexts
  are normally Secondary Context or Tertiary Evidence / Diagnostics
  surfaces.
- These surfaces remain essential for verification, diagnosis, and
  auditability, but they MUST NOT dominate default operator workflows
  or primary navigation merely because the underlying objects exist.

##### Default to decisions, not details

- Default-visible information MUST first answer what happened, why it
  matters, how urgent it is, what the system recommends, what impact
  the decision has, and what action or approval is required now.
- Internal IDs, relation depth, raw payloads, full snapshot history,
  debug views, and unstructured technical detail MUST stay secondary
  unless they are required for the first decision.

##### Progressive disclosure is the default

- Depth MUST be preserved but revealed on demand through
  expand/collapse, drawers, tabs, side panels, explicit "Show details"
  affordances, or focused drill-downs from a clear decision context.
- The default workflow SHOULD let the operator decide before navigating
  through diagnostic depth.
- Primary flows MUST NOT force operators through multiple technical
  subpages before a single governance decision can be made.

##### Navigation follows workflows, not storage structures

- Primary navigation and prominent entry points MUST follow operator
  workflows such as pending decisions, alerts / escalations, reviews,
  exceptions / accepted risks, governance priorities, and blocked or
  failed automations.
- Internal persistence terms such as OperationRuns, EvidenceItems,
  PolicyVersions, StoredReports, or relational chains MAY exist as
  supporting surfaces, but they do not earn primary information
  architecture status by default.
- Every navigation proposal MUST answer: does this reflect a working
  task or only an internal storage structure?

##### Meaning comes before model names

- Operator-facing surfaces MUST prefer governance language such as
  "Drift detected", "Exception expires soon", "Evidence incomplete",
  "Review ready", "Remediation recommended", or "Further review
  required".
- Model names, table/entity language, relation terminology, and
  implementation-first state labels MUST NOT be the primary UX
  language when business meaning can be expressed directly.

##### One case, one decision context

- A single governance case SHOULD be decidable within one focused
  context that brings together the problem, risk or relevance,
  recommendation, impact, ownership, next action, approval options, and
  optional detail beneath or beside the decision.
- Operators MUST NOT be forced to reconstruct one decision across
  multiple equal-rank Run, Evidence, Policy, Audit, and Finding pages
  when the product can present one coherent decision context.

##### Audit depth is mandatory; dominance is not

- Enterprise-grade evidence, verification, and audit depth MUST remain
  available.
- Audit requirements do NOT justify default surfaces that look or
  behave like forensic diagnostics consoles.
- The standard operator flow SHOULD remain calm, prioritized, and
  decision-led even when deep proof is available.

##### New primary surfaces require strict justification

- Every new top-level or otherwise prominent surface MUST justify:
  1. which human-in-the-loop moment it supports,
  2. why an existing surface is insufficient,
  3. why a drawer, panel, tab, or embedded decision context is
     insufficient,
  4. what search, review, or click work it removes.
- If those answers are weak, the work MUST reuse an existing decision
  context or remain secondary/tertiary.

##### Automation must reduce attention load

- New automation, notification, or autonomous governance behavior MUST
  measurably reduce search work, review work, or click load.
- Automation that primarily creates extra lists, statuses, surfaces, or
  detail work is non-conformant even if technically correct.
- The review question is: does this make the platform quieter and
  clearer, or merely larger?

##### Calm default surfaces

- The default workspace experience MUST distinguish clearly between
  immediately actionable work, worth-watching context, and
  reference-only information.
- Unranked warning floods, parallel attention entry points, and
  perpetual visual escalation are forbidden on primary surfaces.
- A surface that only creates noise instead of priority is
  non-conformant.

##### Retrofit requirement

- DECIDE-001 applies to existing as well as new surfaces.
- Existing surfaces MUST be reclassified as Primary Decision,
  Secondary Context, or Tertiary Evidence / Diagnostics surfaces and
  then reviewed for prominence, disclosure, consolidation, and
  workflow alignment.
- Surface retrofit work SHOULD prefer reclassification and
  consolidation before creating new navigation branches.

##### Review gate

Every operator-facing spec or PR that changes a surface MUST answer:
1. What concrete decision or operator action does this support?
2. Who is the human in the loop?
3. What MUST be immediately visible for the first decision?
4. What is preserved but only revealed on demand?
5. Is this a Primary Decision Surface, Secondary Context Surface, or
   Tertiary Evidence / Diagnostics Surface?
6. If it is primary, why can it not live inside an existing decision
  context?
7. Does the navigation reflect a workflow or only storage structure?
8. Does this reduce search, review, or click work?
9. Does this make the product calmer and clearer instead of louder?

#### Audience-Aware Decision Surfaces & Disclosure Ladder (DECIDE-AUD-001)

Goal: every operational, governance, evidence, onboarding, review, and
support-facing detail or status surface MUST keep customer-readable
decision content, operator diagnostics, and support/raw evidence
intentionally separated while preserving full depth through progressive
disclosure.

##### Audience ladder is explicit

- In-scope detail and status surfaces MUST define their content using
  this three-tier hierarchy when applicable:
  - decision content
  - operator diagnostics
  - support / raw evidence
- Surfaces that are reachable by more than one audience class MUST
  define their default-visible content for at least these layers when
  applicable:
  - customer / read-only default
  - operator / MSP diagnostics
  - platform / support raw evidence
- The surface contract MUST state which capabilities unlock each deeper
  layer.
- Support/raw evidence MUST NOT become the default first-read
  experience on customer-readable or ordinary operator-facing
  surfaces.

##### Customer-readable default path

- The default reading path for customer/read-only users MUST optimize
  for status, reason, impact, one dominant next action, and a short
  result or artifact summary.
- Internal lifecycle wording, debug semantics, implementation field
  names, raw payload fragments, and support-oriented context MUST NOT
  appear in the default customer-readable path unless they are the only
  way to understand the first decision.
- Default-visible customer/read-only content is responsible for status,
  reason, impact, the dominant next action, and a concise supporting
  summary only.

##### Diagnostics are secondary by default

- Diagnostics such as lifecycle, timings, verification detail, drift
  detail, permission detail, provider summaries, or related-operation
  context MUST be lower-priority than the decision surface and MUST be
  collapsed, tabbed, grouped, or otherwise progressively disclosed when
  the first decision does not require them.
- Authorized operators MAY expand diagnostics, but diagnostics MUST NOT
  visually compete with the primary decision block.
- Where no support/raw tier is exposed, diagnostics still remain below
  the decision tier and MUST NOT restate the same decision summary at
  equal weight.

##### Raw/support evidence is gated

- Raw/support evidence such as JSON, raw context payloads,
  fingerprints, internal reason ownership, platform reason families,
  monitoring detail, viewer context, or copy/show-raw actions MUST NOT
  appear in the default decision path.
- These details MUST live behind explicit reveal affordances and MUST
  be capability-gated wherever the audience model distinguishes support
  or platform users from ordinary operators.
- Capability-gated support/raw disclosure MUST fail closed when the
  actor lacks the required scope or capability.

##### One dominant next action

- A decision surface MUST expose exactly one dominant next action in
  the default-visible region.
- Optional secondary actions MAY exist, but they MUST NOT compete with
  the primary remediation or decision action in prominence.
- Contextual navigation such as opening a related run, tenant, report,
  or technical detail remains secondary.

##### No duplicate truth across equal-priority cards

- The same blocker, reason, or next action MUST NOT be repeated across
  multiple equal-priority cards, sections, or summary blocks on the
  same default-visible surface.
- Supporting evidence MAY restate the underlying proof, but the
  dominant decision message appears once and diagnostics elaborate
  beneath it.

##### Required tests

- New or materially changed customer/operator-facing detail surfaces
  MUST include focused tests proving:
  - default-visible content shows status, reason, impact, and next
    action,
  - exactly one dominant next action is primary,
  - diagnostics are secondary or collapsed,
  - raw/support evidence is not default-visible,
  - support/raw sections are capability-gated where applicable,
  - and duplicate visible decision summaries are absent.

##### Stored evidence wins over fallback diagnostics

- When a stored verification or report artifact exists, fallback
  technical diagnostics SHOULD demote behind supporting evidence or
  technical details instead of remaining peer-level default content.
- Fallback diagnostics MAY become temporarily prominent only when the
  higher-level artifact does not yet exist or is unavailable.

#### Surface Taxonomy (UI-SURF-001)

Every new admin surface MUST be assigned exactly one broad action-surface
class before implementation. Ad-hoc interaction models are forbidden.

The allowed broad action-surface classes are:
- Record / Detail / Edit
- Monitoring / Queue / Workbench
- List / Table / Bulk
- Wizard / Flow
- Utility / System

Operator-facing surfaces MUST also declare exactly one detailed surface
type from the taxonomy below. The broad class determines the action
hierarchy first; the detailed surface type refines it.

##### CRUD / List-first Resource
- Purpose: scan, find, open, and selectively mutate many business records.
- Primary behavior: Browse -> Open -> Decide / Mutate.
- Primary model: one-click inspect/open. Full-row click is the default; identifier click is allowed only when full-row click conflicts with another dominant row mechanism.
- Secondary actions: at most one inline non-destructive shortcut; everything else belongs in overflow.
- Destructive actions: never inline beside inspect; only in overflow or the detail header; confirmation is mandatory.
- Explicit View/Inspect: forbidden when row click or identifier click already opens the same destination.

##### Queue / Review Surface
- Purpose: triage items, inspect them in context, decide, and continue working through the queue.
- Primary behavior: Inspect in context -> Decide -> Continue.
- Primary model: explicit Inspect using a slide-over, inline detail pane, or same-page inspect.
- Secondary actions: only queue-relevant actions belong in the row.
- Destructive actions: inline is allowed only when the destructive decision is part of the real queue work; irreversibility or high risk still requires confirmation.
- Row click: forbidden by default.
- Explicit View/Inspect: required unless the detail is already visible inline.

##### History / Audit Surface
- Purpose: inspect immutable history, events, and evidence without losing chronology.
- Primary behavior: Inspect event -> Follow trace -> Return to history context.
- Primary model: explicit Inspect, preferably in a slide-over or same-page detail.
- Secondary actions: related navigation only.
- Destructive actions: normally none.
- Row click: forbidden.
- Explicit View/Inspect: required.

##### Config-lite Resource
- Purpose: manage small, low-cardinality configuration where edit is effectively the detail surface.
- Primary behavior: Open config -> Adjust.
- Primary model: edit-as-inspect.
- Secondary actions: minimal and usually limited to Edit or overflow.
- Destructive actions: overflow or detail header only.
- Row click: allowed when it opens Edit directly and no separate View surface exists.
- Explicit View/Inspect: forbidden.

##### Read-only Registry / Report Surface
- Purpose: inspect, compare, reference, and export immutable or mostly read-only artifacts.
- Primary behavior: Scan -> Open detail -> Reference / Export.
- Primary model: row click or identifier click to detail.
- Secondary actions: optional single inline non-destructive shortcut when it serves the operator flow.
- Destructive actions: normally none; if they exist they belong in detail only.
- Explicit View/Inspect: forbidden when a functional one-click open already exists.

##### Detail-first Operational Surface
- Purpose: fully understand one operational record, including state, truth, context, and next steps.
- Primary behavior: Read -> Understand -> Act / Navigate.
- Primary model: dedicated detail page or dedicated operational page.
- Secondary actions: header actions and related-link groups.
- Destructive actions: detail header or grouped header actions only, always with confirmation.
- Row click and explicit View/Inspect: not applicable.

##### Native vs custom and shared-family classification
- Every operator-facing surface MUST also classify whether it is a
  `Native Surface`, a `Custom Surface`, or a `Shared Detail Micro-UI`
  embedded inside a `Host`.
- `Native Surface` means the primary interaction contract is expressed
  through Filament-native components or approved shared primitives.
- `Custom Surface` means the operator need is materially richer than
  standard CRUD, overview, or report semantics and the deviation is
  justified through UI-EX-001.
- `Shared Detail Micro-UI` means a repeated embedded review, evidence,
  or detail surface that appears in more than one host and must read as
  the same family wherever it appears.
- `Host` means the page, resource, workbench, or detail surface that
  embeds a shared detail micro-UI and owns routing, authorization, the
  outer inspect/open model, and host-only actions.
- A `Fake-Native Surface` is never an allowed classification. It is a
  violation class defined by UI-HARD-001 and UI-FIL-001.

#### Action Surface Discipline (ACTSURF-001)

Goal: actions across all surfaces MUST make the next sensible operator
step obvious, keep safe navigation distinct from mutation, and prevent
dangerous or governance-relevant actions from sitting casually beside
harmless context changes.

##### Surface class first

- Every new or materially changed surface MUST declare exactly one broad
  action-surface class before actions are designed.
- Different surface classes MAY use different action models only when
  the difference is deliberate, documented, and justified by the
  workflow.
- Detailed surface types refine the rule set; they do not replace the
  broad class requirement.

##### Record / Detail / Edit surfaces

- Classic record/detail/edit pages MUST expose at most one visible
  primary header action.
- Pure navigation MUST NOT live in the header when it can be placed
  inline at summary, field, badge, status, or related-context level.
- Secondary, rare, or administrative actions MUST be grouped.
- Multiple equally weighted mutation buttons in the header are
  forbidden.
- Destructive, irreversible, or governance-relevant actions MUST be
  clearly separated from routine actions.
- The likely next operator step MUST be recognizable within seconds.
- HDR-001 is the binding specialization for record/detail/edit headers.

##### Monitoring / Queue / Workbench surfaces

- Surface-level context, scope context, navigation, selection actions,
  and object actions MUST NOT be mixed as one flat header strip.
- Scope indicators are context signals, not ordinary calls to action.
- Selection-dependent actions SHOULD become prominent only when a
  selection or focused object actually exists.
- Record-page header rules MUST NOT be copied blindly onto workbench
  surfaces.
- Workbench surfaces MAY use a different action model, but that model
  MUST be explicit, repeatable, and internally consistent.

##### List / Table / Bulk surfaces

- Inspect/open affordances MUST remain consistent within the same
  surface class.
- Bulk actions are allowed only for genuine multi-record work.
- Row actions MUST NOT dominate reading and scanning.
- Rare, destructive, or governance-relevant actions MUST NOT accumulate
  casually in default row actions.
- Tables exist primarily to scan, filter, compare, and decide; they
  MUST NOT become unstructured action stockpiles.

##### Wizard / Flow surfaces

- Wizard actions MUST reflect staged progression, explicit back/cancel
  semantics, and safe confirmation at the step where risk becomes real.
- Wizard pages MAY expose more than one visible action when the flow
  genuinely requires progression, backtracking, or guarded cancellation.
- Even in a wizard, the next primary step MUST remain obvious.

##### Utility / System surfaces

- Utility and system pages MAY use narrower tooling-oriented action
  sets, but they MUST still separate safe navigation, routine control,
  and dangerous intervention.
- System or recovery status does not justify casual placement of
  destructive or governance-changing actions.

##### Shared detail families and one primary interaction model

- A shared detail micro-UI MUST define one family-level core
  interaction model before a second host extends it.
- Hosts MAY vary framing, assist entry, surrounding navigation, or
  optional diagnostics only when the shared core remains recognizable
  and the variation is explicit.
- The host owns page-level navigation, authorization, surrounding
  mutations, and dangerous actions. The shared family owns only the
  repeated read/inspect/view semantics that are intentionally common.
- One user concern MUST NOT be split across two peer interaction
  models on the same page.
- `Parallel Inspect Worlds` means the same concern is driven by two
  competing inspect, selected-record, or view-state owners. It is
  forbidden.

##### Action grouping and order

- Actions MUST be ordered by meaning, frequency, and risk.
- The preferred order is:
  1. primary next step
  2. common secondary action
  3. rare or contextual action
  4. dangerous or irreversible action
- An `ActionGroup` / More menu is not a junk drawer. Navigation,
  mutation, external links, and destructive actions inside a group MUST
  still be named, ordered, and separated coherently.

##### Navigation vs mutation

- Navigation and mutation are different intent classes and MUST NOT
  appear as equal-weight peers without explicit hierarchy.
- Harmless context switches MUST NOT visually overpower
  governance-relevant actions.
- Pure context navigation SHOULD live near the content it concerns
  rather than as header filler.

##### Governance friction

- Actions with risk, blast radius, or irreversible effect MUST use
  shared governance-friction rules rather than per-surface improvisation.
- Depending on impact, the required friction is confirmation, optional
  reason, mandatory reason, typed confirmation, or staged flow.
- Clear danger semantics and separated placement are mandatory for
  dangerous or governance-changing actions.

##### Exceptions require explicit reason

- New surfaces MAY deviate only when the surface class or workflow truly
  requires it.
- Allowed justification labels are:
  - Special type
  - Workflow hub
  - Wizard
  - Utility / System surface
  - Another clearly defined exception documented in the governing spec
- "Historically grew this way" and "it was easy to add to the header"
  are invalid reasons.

##### Reuse before invention

- New features MUST reuse existing disciplined patterns, reference
  architectures, and shared primitives when they fit the chosen surface
  class.
- Reference patterns are reuse baselines, not automatic mandates for
  every surface.

##### Constitution over convenience

- Local implementation speed MUST NOT override consistent action
  hierarchy.
- No new feature may introduce:
  - multiple equal-rank header mutations without a clear primary
  - navigation as casual header filler
  - unreflective mixing of record, workbench, and governance patterns
  - new local exceptions without explicit rationale

##### Review gate

Every new or materially changed surface with actions MUST answer:
1. What broad action-surface class is it?
2. What is the one most likely next operator action?
3. Is navigation cleanly separated from mutation?
4. Are rare or risky actions removed from the primary plane?
5. Is the hierarchy scanable in a few seconds?
6. If this is a repeated detail family, what is shared core vs
   host-owned variation?
7. Does one concern still have exactly one primary interaction model?
8. Which layer owns the relevant truth: shell, page, or detail?
9. Is any exception real, bounded, and named, or is it a hidden
   exception?

If those answers are not clear, the surface is non-conformant.

##### Canonical outcome

- The goal is not the smallest possible number of buttons.
- A conformant surface highlights the next sensible step, separates
  context, navigation, mutation, and danger cleanly, remains structured
  as capability grows, and applies the same principles consistently
  across the product.

#### Hard Rules (UI-HARD-001)

##### Primary inspect model
- Every list surface MUST expose exactly one primary inspect/open model.
- A surface MUST NOT offer row click, identifier click, and explicit View/Inspect for the same destination as parallel primary models.
- CRUD / List-first and Read-only Registry / Report surfaces MUST provide an obvious one-click open path.
- Queue / Review and History / Audit surfaces MUST use explicit Inspect rather than row-click navigation.
- Inline detail, summary, or sidebar inspect MAY exist only as
  subordinate presentations of the same selected-record truth, not as a
  second inspect contract.
- `Parallel Inspect Worlds` are forbidden even when each local variant
  looks individually reasonable.

##### Row-click semantics
- Full-row click is the default for CRUD / List-first and Read-only Registry / Report surfaces.
- Identifier-only click is allowed only when full-row click would conflict with another dominant row behavior such as selection-heavy interaction, expand/collapse, drag/sort, or another primary row mechanism.
- When row click is enabled, the row MUST feel consistent. Silent split behavior inside the same row is forbidden.
- Edit-as-inspect is allowed only for Config-lite resources.

##### View and Inspect actions
- Explicit View MUST NOT exist when the same destination is already opened through row click or identifier click.
- Explicit Inspect is the default only for Queue / Review, History / Audit, and explicitly catalogued exceptions.
- View and Inspect MUST NOT be treated as interchangeable labels. If the interaction preserves context and behaves unlike ordinary navigation, it is Inspect, not View.

##### Action hierarchy
- Every surface MUST distinguish between the primary inspect/open action, secondary safe actions, destructive actions, and long-running workflow launches.
- Standard CRUD and Read-only Registry rows MUST NOT exceed the primary open interaction plus one inline safe shortcut.
- All other secondary actions MUST move to overflow.
- Long-running workflow launches such as sync, compare, verify, generate, consent, setup, or retry SHOULD live in list headers or detail headers rather than in every row.

##### Native-by-default and fake-native drift
- Standard form, filter, table, action, tab, badge, link, and overview
  work is `Native Surface` work by default when Filament or an existing
  shared primitive can express it.
- A `Fake-Native Surface` is any surface that visually lives inside
  Filament but keeps a second HTML, GET, query, or Blade-request
  interaction contract for its primary behavior.
- Simple report or overview pages with ordinary columns, filters, empty
  states, and navigation default to native table semantics.
- `Filament Costume` means locally assembled markup imitates native
  Filament controls, badges, or actions even though native or shared
  primitives fit. It is forbidden.
- `Blade Request UI` means the primary body-state contract depends on
  `request()`, GET forms, or manual query parsing inside an active
  Filament surface. It is forbidden unless a documented exception limits
  request input to initialization-only behavior.
- `Hand-Rolled Simple Overview` means a simple report or overview is
  rebuilt as bespoke markup where native table/list/report semantics
  fit. It is forbidden.
- `Hidden Exception` means a surface behaves like a custom or special
  case without naming an exception type and reason block. It is
  forbidden.

##### Destructive actions
- Destructive actions MUST NOT appear inline beside the primary inspect interaction on standard CRUD, Config-lite, or Read-only Registry surfaces.
- Destructive actions MUST live in overflow or the detail header.
- Destructive actions MUST use confirmation.
- High-risk or high-volume destructive bulk actions SHOULD use typed confirmation.
- The Queue Decision exception applies only when the destructive decision is part of the actual queue work.

##### Overflow and More
- Overflow actions MUST follow one product-wide pattern per surface class.
- Mixed labeled-overflow versus icon-only overflow patterns inside the same surface class are forbidden unless an approved exception documents why.
- Empty `ActionGroup` and empty `BulkActionGroup` are forbidden.
- Placeholder UI added only to satisfy a contract or slot is forbidden.

##### Bulk actions
- Bulk actions are allowed only when they are safe enough, materially faster than row-by-row execution, and genuinely fit the surface.
- A surface with no real bulk need MUST NOT render bulk UI.
- Bulk destructive actions follow the same protection rules as row destructive actions, with stricter confirmation and review expectations.

##### Row label length and action budget
- Inline row action labels MUST stay short and SHOULD be one or two words.
- Long workflow labels belong in overflow, headers, or detail surfaces.
- Standard list rows MUST NOT become control centers for onboarding recovery, provider management, consent flows, RBAC setup, diagnostics, and destructive lifecycle actions all at once.

##### Scope and context semantics
- Scope chips, tenant pills, and similar context signals MUST correspond to real scoping behavior.
- A scope signal MUST NOT be shown when it neither scopes the displayed data nor materially changes the action targets.
- Remembered context is allowed only when labeled clearly as reference context rather than active scope.
- Cross-panel navigation MUST NOT imply that the operator remains inside the same logical scope when that is not true.

##### Canonical navigation and terminology
- Every domain object MUST have one canonical collection noun and one canonical singular noun.
- The same domain object MUST NOT use competing primary nouns across shells.
- The Operations domain MUST use one canonical collection noun. Parallel primary nouns such as Runs beside Operations are forbidden.
- Cross-panel navigation is allowed only when it lands on a canonical surface, uses stable nouns, and keeps back navigation clear.

##### Visibility of critical operational truth
- Critical operational truth MUST be visible by default.
- It MUST NOT be hidden only in default-off columns, tooltips, helper text, overflow menus, or detail pages when list decisions depend on it.
- Lifecycle truth, operability truth, health truth, execution outcome, trust/confidence, and next action MUST remain separate semantic dimensions.
- One badge, column, or label MUST NOT collapse multiple truth dimensions into a generic status.

##### Row density and scanability
- Standard CRUD lists MUST remain scanable.
- Outside Queue / Review and History / Audit exceptions, each row MAY contain at most one multi-line explanatory column and at most one prose-heavy explanatory context.
- Standard CRUD rows MUST NOT carry more than one sentence of flowing prose.
- Next-step prose belongs in detail, inspect, or queue surfaces, not in ordinary CRUD rows.

##### Shared-family and state-layer violations
- `Host Drift` occurs when a host silently redefines a shared detail
  micro-UI's core zones, diagnostics contract, or primary view/inspect
  model. Host Drift is forbidden.
- `State Layer Collapse` occurs when shell, page, or detail layers each
  claim the same active truth or restoration responsibility. It is
  forbidden.
- A lower layer MAY format or reveal a higher-layer truth, but it MUST
  NOT quietly become the higher layer's authority.

##### Custom abstractions
- Custom UI abstractions MAY document and validate, but they MUST NOT create declaration-only safety that diverges from real behavior.
- Contract systems MUST NOT force placeholder UI.
- Behavior matters more than declaration. If declared conformance and rendered behavior differ, the surface is non-conformant.
- A feature MUST NOT ship when its implemented interaction semantics contradict its declared surface type.

#### Exception Model (UI-EX-001)

Only catalogued exception types are allowed. Every exception MUST be named in the spec, reference its exception type, include a reason block, be called out explicitly in the PR, and carry at least one dedicated test.

- A `Legitimate Exception` is a named, bounded deviation that states the
  product reason, the smallest custom behavior required, what remains
  standardized, which layer owns the relevant state, and what proof or
  review evidence keeps it from turning into a general permission slip.

##### Queue Decision Exception
- Allowed when per-item decision-making is the real queue work.
- Guardrails: Inspect remains available unless detail is already inline; irreversible decisions require confirmation; unrelated maintenance actions do not join the row.

##### History In-place Inspect Exception
- Allowed when leaving the page would break chronology or traceability.
- Guardrails: explicit Inspect is mandatory; row click is forbidden; generic mutation rails are forbidden.

##### Config-lite Edit-as-Inspect Exception
- Allowed when a separate View surface would add no value.
- Guardrails: no parallel View surface; no high-risk destructive flow as the default entry point.

##### Read-only Shortcut Exception
- Allowed for exactly one dominant non-destructive shortcut.
- Guardrails: inspect/open remains dominant; only one shortcut exists; the shortcut does not compete with the primary open path.

##### Cross-panel Canonical Route Exception
- Allowed when only one canonical surface makes sense.
- Guardrails: nouns stay stable; shell transition is explicit; back navigation is clear; scope signals remain truthful.

##### Legitimate Custom Surface Exception
- Allowed when the operator need is materially richer than ordinary
  CRUD, overview, or simple report semantics, such as richer
  visualization, high-value diagnostic or review work, multi-zone shared
  detail micro-UI, shell-context-specific UI, or domain presentation
  that native primitives do not express cleanly.
- Guardrails: the spec MUST state the product reason, the smallest
  custom behavior required, which native/shared primitives still apply,
  which layer owns the relevant state, and what remains standardized.

##### Nativity Exception
- Allowed only when Filament-native or shared primitives cannot express
  the required semantics cleanly.
- Guardrails: the exception MUST name the missing semantic, reject
  `Filament Costume`, `Blade Request UI`, and `Hand-Rolled Simple
  Overview` shortcuts, keep native/shared surrounding controls where
  they still fit, and MUST NOT invent a local status language.

##### Shared Detail Host Variation Exception
- Allowed when a known shared detail micro-UI needs bounded host
  framing, assist entry, or optional-zone variation.
- Guardrails: the host MUST NOT redefine the family core zones,
  next-step contract, diagnostics contract, or primary view/inspect
  model. Differences stay visibly host-scoped.

##### State-Layer Special-case Exception
- Allowed when a page legitimately needs explicit requested, active,
  draft, inspect, or restorable roles beyond the simple default.
- Guardrails: the owner layer MUST be explicit, the restorable subset
  MUST be explicit, any query role MUST be documented, and no lower
  layer may silently take over shell or page truth.

#### Filament UI — Action Surface Contract (NON-NEGOTIABLE)

For every new or modified Filament Resource, RelationManager, or Page:

Required surfaces
- List/Table MUST define Header Actions, Row Actions, Bulk Actions, and Empty-State CTA(s).
- Every table MUST provide a record inspection affordance that matches its surface type.
- Accepted forms are `recordUrl()` row click, a primary linked column, or an explicit row action when the taxonomy requires Inspect.
- CRUD / List-first, Config-lite, and Read-only Registry surfaces MUST NOT render a redundant View action when the same destination is already available through row click or identifier click.
- Queue / Review and History / Audit surfaces MAY use a lone explicit Inspect action because context-preserving inspect is the primary interaction.
- Simple report or overview pages with ordinary columns, filters,
  empty-state behavior, and navigation MUST be implemented as native
  table surfaces unless UI-EX-001 documents why a richer custom surface
  is required.
- View/Detail MUST define header actions and MUST keep destructive actions grouped and confirmed.
- View/Detail MUST be sectioned using Infolists, Sections, Cards, Tabs, or equivalent composable structure.
- Create/Edit MUST provide consistent Save and Cancel UX.

Grouping and safety
- Standard CRUD and Read-only Registry rows MUST NOT exceed inspect/open plus one inline safe shortcut.
- Queue / Review rows MAY expose inline decision actions only when allowed by UI-EX-001.
- Everything else MUST move to `ActionGroup::make()` or the detail header.
- Repeated embedded detail/evidence families MUST declare one shared
  core contract. Host-specific navigation, mutations, and destructive
  actions stay outside that shared core.
- Bulk actions MUST be grouped via `BulkActionGroup` only when the surface has a real bulk use case.
- Empty `ActionGroup` and `BulkActionGroup` are forbidden.
- Destructive actions MUST NOT be primary and MUST require confirmation; typed confirmation MAY be required for large or high-risk bulk changes.
- Relevant mutations MUST write an audit log entry.

RBAC enforcement
- Non-member access MUST abort(404) and MUST NOT leak existence.
- Members without capability MAY see disabled actions with helper text, but server-side execution MUST still abort(403).
- Central tenant and workspace UI enforcement helpers MUST be used for gating.

Behavior over declaration
- Every spec MUST include both a UI/UX Surface Classification and a UI Action Matrix.
- Every changed operator-facing surface MUST declare its broad
  action-surface class and the one most likely next operator action.
- Every changed operator-facing surface MUST also declare whether it is
  a `Native Surface`, `Custom Surface`, or `Shared Detail Micro-UI`, and
  MUST name any exception type it relies on.
- If a surface uses shell, page, or detail state beyond simple static
  rendering, the governing spec MUST name which layer owns the relevant
  requested, active, draft, inspect, and restorable state.
- Custom action-surface contracts are legitimate only when they validate rendered behavior, not only declarations or slot counts.
- A change is not Done unless the implemented interaction semantics conform to the declared surface type or an approved exception documents and tests the deviation.

#### Filament UI — Layout & Information Architecture Standards (UX-001)

Goal: operator-facing Filament screens MUST feel enterprise-grade, legible, and decisive.

Page layout
- Create/Edit MUST default to a Main/Aside layout using a 3-column grid with `Main=columnSpan(2)` and `Aside=columnSpan(1)`.
- All fields MUST live inside Sections or Cards. Naked root-level inputs are forbidden.
- Main content carries domain definition and working content. Aside carries status and meta such as scope, owner, timestamps, or version labels.
- Related data MUST render as separate sections, tabs, or subordinate surfaces rather than as one long unstructured form or detail page.

View pages
- View/Detail MUST be a read-only surface built with Infolists or an equivalent read-first structure, not disabled edit forms.
- Status-like values MUST render via BADGE-001 semantics.
- Long text MUST read like prose, not like disabled textarea output.

Empty states
- Empty lists and tables MUST show a specific title, a one-sentence explanation, and exactly one primary CTA.
- When records exist, that primary CTA moves to the header and MUST NOT be duplicated in the empty state shell.

Actions and flows
- Record / Detail / Edit pages MUST expose at most one visible primary
  header action. Any additional visible secondary header action requires
  explicit justification under ACTSURF-001 / HDR-001; the rest belong in
  groups or contextual placement.
- Multi-step or high-risk flows MUST use a wizard or an equivalent staged flow with preview and confirmation.
- Destructive actions remain non-primary and confirmed.

Table defaults
- Tables SHOULD provide search when the dataset can grow, a meaningful default sort, and filters for core dimensions.
- Standard CRUD tables MUST stay scanable and MUST NOT rely on row prose to communicate next steps.
- Critical operational truth that informs list decisions MUST be default-visible.

State ownership
- `Global Context State` is shell-owned workspace, tenant, or tenantless
  truth. Context bars and shell partials may display it, but they MUST
  NOT invent second precedence or fallback logic.
- `Page State` is page-owned filter, tab, mode, or selected-record truth
  that changes the current page result or workflow.
- `Detail State` is embedded viewer or shared-family state inside one
  detail surface and remains subordinate to shell and page truth unless
  an approved exception says otherwise.
- `Requested State` is route, query, or upstream input before validation.
- `Active State` is the currently governing validated state.
- `Draft State` is local pending state that is intentionally separate
  from the currently applied result state.
- `Inspect State` is the selected-record or selected-detail focus that
  drives inline or same-page inspect.
- `Restorable State` is the subset intentionally recreated by refresh,
  back, bookmark, or shared link.
- `State Layer Collapse` is forbidden. Shell, page, and detail layers
  MUST NOT silently overwrite one another's authority.

Enforcement
- Shared layout builders such as `MainAsideForm`, `MainAsideInfolist`, and `StandardTableDefaults` SHOULD be reused where available.
- A change is not Done unless UX-001 is satisfied or an approved exception documents why not.

#### Record / Detail / Edit Header Discipline & Contextual Navigation (HDR-001)

Goal: record, detail, and edit pages MUST be comprehensible within
seconds. HDR-001 is the binding record/detail/edit specialization of
ACTSURF-001.

Header actions are reserved for the primary workflow of the current page
and MUST NOT become a dumping ground for every available action or
navigation jump.

##### Core rule

Header actions MUST contain only workflow-critical actions of the
currently displayed record. Pure navigation, relational jumps, and
contextual references do not belong in the header; they belong directly
at the affected field, status indicator, or relation.

##### Shared-family host discipline

- If a record or detail page embeds a shared detail micro-UI, the
  header remains host-owned.
- Family-level view switches, tabs, diagnostics reveals, and inner
  assist controls belong inside the family, not as copied header
  buttons.
- Host-specific navigation or mutations MAY appear in the header only
  when they are truly host-critical and do not redefine the family core.

##### Maximum one primary visible header action

- Each record/detail page MUST expose at most one clearly prioritized
  primary visible header action.
- That action MUST represent the most obvious next operator step on
  exactly this page.
- Multiple equally weighted mutation buttons in the header are
  forbidden.

##### Navigation does not belong in headers

- Actions such as "Open finding", "Open queue", "View related run",
  "Open tenant", or similar jumps are navigation actions, not primary
  object actions.
- They MUST be placed as contextual navigation at fields, badges,
  relation entries, or status displays — never in the header.

##### Destructive or governance-changing actions require friction

- Actions with operational, security-relevant, or governance-changing
  effect MUST NOT stand at the same visual level as the primary action.
- They MUST either:
  - be rendered as a clearly separated danger action, or
  - be placed in an Action Group / More Actions.
- They MUST always require explicit confirmation
  (`->requiresConfirmation()`).
- If an action changes governance truth, compliance status, risk
  acceptance, exception validity, or equivalent system truths,
  additional friction is mandatory (e.g., typed confirmation, reason
  field, or staged flow).

##### Rare secondary actions belong in an Action Group

- Actions that are not part of the expected core workflow of the page
  or are only occasionally needed MUST NOT appear as equally weighted
  visible header buttons.
- They MUST be placed in an Action Group.
- The Action Group itself MUST remain structured; it MUST NOT become an
  unlabelled mix of navigation, external links, mutations, and danger.

##### Header clarity over implementation convenience

- The fact that a framework makes header actions easy to add is not a
  reason to place actions there.
- Information architecture, scanability, and operator clarity take
  precedence over implementation convenience.

##### 5-second scan rule

Every record/detail page MUST pass the 5-second scan rule:

1. The operator instantly recognizes where they are.
2. The operator instantly sees the status of the object.
3. The operator instantly identifies the one central next action.
4. The operator immediately understands where secondary or dangerous
   actions live.

If multiple equally weighted header buttons degrade this readability,
it is a constitution violation.

##### Placement rules

Allowed in the header:
- One primary workflow action.
- Optionally one clearly justified secondary action.
- Rare or administrative actions only when grouped.
- Critical/destructive actions only when separated and with friction.

Forbidden in the header:
- Pure navigation to related objects.
- Relational jumps without immediate workflow relevance.
- Collections of technically available standard actions.
- Multiple equally weighted buttons without clear prioritization.

##### Preferred pattern

| Slot | Placement |
|---|---|
| Primary visible | Exactly 1 |
| Danger | Separated or grouped, never casual beside Primary |
| Navigation | Inline at context (field, badge, relation) |
| Rare actions | More / Action Group |

##### Binding decision — Exception / Approval surfaces

For exception detail pages specifically:
- **Renew exception** MAY appear as the primary visible header action.
- **Revoke exception** is a governance-changing danger action and MUST
  require friction (separated + confirmation).
- **Open finding** MUST be placed as a link at the Finding field, not
  in the header.
- **Open approval queue** MUST be placed as a contextual link at
  approval / status context, not in the header.

##### Reviewer heuristics

A page violates HDR-001 if any of the following are true:
- Multiple equally weighted header actions without clear workflow
  priority.
- Pure navigation buttons in the header.
- Danger actions beside normal actions without clear separation.
- Rarely used administrative actions as visible standard buttons.
- Shared-family view switches or host-only forks are exported into the
  main header instead of staying inside the family or contextual
  placement.
- The header resembles an action stockpile instead of a focused
  workflow entry point.

#### Operator-facing UI Naming Standards (UI-NAMING-001)

Goal: operator-facing actions, runs, notifications, audit prose, and navigation MUST use one clear domain vocabulary.

Naming model
- Operator-facing copy MUST distinguish Scope, Source/Domain, Operation, and Target Object.
- Scope terms such as Workspace and Tenant describe execution context and MUST NOT become the primary action label unless they are the actual target object.
- Source/domain terms such as Intune or Entra are secondary and lead only when same-screen disambiguation genuinely requires them.

Primary labels
- Primary buttons, header actions, and menu actions MUST use Verb + Object.
- Preferred examples are `Sync policies`, `Sync groups`, `Capture baseline`, `Compare baseline`, `Restore policy`, `Run review`, and `Export review pack`.
- Implementation-first labels such as `Sync from tenant`, `Sync from Intune`, `Run tenant sync now`, or `Start inventory refresh from provider` are forbidden.

Canonical nouns and routes
- Every domain object MUST keep one canonical collection noun and one canonical singular noun.
- Cross-shell or cross-panel navigation MUST preserve the same noun.
- Operations is the canonical collection noun for run records. Runs MUST NOT appear as a competing primary collection noun.

Run, notification, and audit semantics
- Visible run titles MUST use the same domain vocabulary as the initiating action and SHOULD remain concise noun phrases such as `Policy sync`, `Baseline capture`, `Baseline compare`, `Policy restore`, and `Tenant review`.
- Notifications MUST use either `{Object} {state}` or `{Operation} {result}` and remain short.
- Audit prose MUST use the same operator-facing language as the initiating action.
- The same user-visible action MUST keep the same domain vocabulary across button labels, modal titles, run titles, notifications, audit prose, and related navigation.

Verb standard
- Preferred verbs are `Sync`, `Capture`, `Compare`, `Restore`, `Review`, `Export`, `Open`, `Archive`, `Resolve`, `Reopen`, and `Assign`.
- `Start`, `Execute`, `Trigger`, and `Perform` SHOULD be avoided unless the domain specifically requires them.
- `Run` MAY be used only when the object is itself run-like, such as `Run review`; it MUST NOT become the fallback verb for everything.

Current binding decision
- The Policies screen primary action MUST be `Sync policies`.
- The Policies screen modal title MUST be `Sync policies`.
- The Policies screen success toast MUST be `Policy sync queued`.
- The visible run label for that action MUST be `Policy sync`.
- The audit prose for that action MUST be `{actor} queued policy sync`.

#### Operator Surface Principles (OPSURF-001)

Goal: operator-facing surfaces MUST optimize for the operator's working question instead of raw implementation visibility.

Operator-first default surfaces
- `/admin` is operator-first.
- Default-visible content MUST use operator language, clear scope, and actionable status communication.
- Raw implementation details MUST NOT be default-visible on primary operator surfaces.

Progressive disclosure for diagnostics
- Diagnostic detail MAY exist, but it MUST be secondary and explicitly revealed.
- JSON payloads, raw IDs, internal field names, provider error details, and low-level technical metadata belong in diagnostics surfaces rather than the primary content region.
- Operators MUST NOT need to parse raw payloads to understand current state or next action.
- Detail/status surfaces MUST satisfy DECIDE-AUD-001: decision content
  first, operator diagnostics second, support/raw evidence third.

Distinct truth dimensions
- When the domain has execution outcome, data completeness, governance result, lifecycle or readiness state, operability truth, health truth, trust/confidence, or next action semantics, the surface MUST keep them explicit instead of collapsing them into one ambiguous status.
- If multiple truth dimensions are summarized, the default-visible UI MUST label each dimension clearly.

Dominant next action and duplicate-truth control
- Default-visible decision content MUST include status, reason,
  impact, and one dominant next action where those concepts exist.
- Secondary navigation or debug helpers MUST remain lower-priority
  than the dominant decision action.
- The same blocker, reason, impact, or next action MUST NOT be
  repeated across multiple default-visible cards, sections, tabs, or
  summaries.

Explicit mutation scope
- Every state-changing action MUST communicate before execution whether it affects TenantPilot only, the Microsoft tenant, or simulation only.
- Mutation scope MUST be understandable from nearby action copy, helper text, preview, or confirmation.

Safe execution
- Dangerous actions MUST follow a consistent safety flow: configuration, safety checks or simulation, preview, hard confirmation where required, then execution.
- One-click high-blast-radius actions are forbidden unless an approved exception documents replacement safeguards.

Explicit workspace and tenant context
- Workspace and tenant context MUST remain explicit in navigation, action copy, and page semantics.
- Tenant surfaces MUST NOT silently expose workspace-wide actions.
- Canonical workspace views that operate on tenant-owned records MUST make both workspace and tenant context legible before the operator acts.

Critical truth visibility and scanability
- Critical operational truth MUST be default-visible wherever the list or summary surface is used to prepare decisions.
- Standard CRUD surfaces MUST preserve scanability and MUST avoid collapsing multiple truth dimensions into one generic badge or one prose-heavy row.

Page contract requirement
- Every new or materially refactored operator-facing page MUST define the primary persona, surface type, primary operator question, default-visible information, diagnostics-only information, status dimensions used, mutation scope, primary actions, and dangerous actions.
- The page contract MUST live in the governing spec and stay in sync with implementation.
- Where multiple audience classes share the page, the contract MUST
  explicitly define the customer/read-only default path, operator
  diagnostics path, support/raw-evidence path, and the capabilities
  that unlock each layer.
- The page contract MUST also make the dominant next action,
  duplicate-truth prevention, and raw/support gating explicit for
  changed detail/status surfaces.

#### Spec Scope Fields (SCOPE-002)

- Every feature spec MUST declare Scope, Primary Routes, Data Ownership, and RBAC requirements.
- Canonical-view specs MUST define the default filter behavior when tenant context is active and the entitlement checks that prevent cross-tenant leakage.

#### Enforcement Model (UI-REVIEW-001)

Spec review requirements
- Every spec that changes an operator-facing surface MUST answer:
  decision-role prominence, human-in-the-loop moment, immediate-visible
  decision information, on-demand evidence/diagnostics boundary,
  whether a new primary surface is actually justified, broad
  action-surface class, detailed surface type, one likely next operator
  action, primary inspect/open model, row-click rule, whether explicit
  View/Inspect exists or is forbidden, where navigation lives, where
  secondary actions live, where destructive actions live, how grouped
  actions are ordered, canonical collection route, canonical detail
  route, scope signals and their exact meaning, canonical noun,
  critical truth visible by default, workflow-vs-storage IA
  justification, attention-load reduction, whether the surface is
  native, custom, or a shared detail family, what shared core vs host
  variation exists if relevant, which layer owns the relevant shell,
  page, and detail truth, which requested/active/draft/inspect/
  restorable roles exist, which audience ladder and disclosure
  boundaries exist, what the dominant next action is, how raw/support
  evidence is gated, how duplicate truth is prevented, whether any
  fake-native or host-drift risk is present, and whether an exception
  type is used.
- Missing any of those answers makes the spec incomplete.

PR review requirements
- A PR MUST NOT pass when it introduces more than one primary inspect
  model, redundant View beside row click, destructive inline actions
  beside inspect on standard lists, empty overflow or bulk groups, long
  workflow labels in dense rows, misleading scope chips, drifting domain
  nouns, hidden critical operational truth, flat record headers with
  multiple equal-weight mutations, workbench headers that mix scope,
  selection, navigation, and object actions as peers, a primary surface
  with no clear human-in-the-loop purpose, detail/evidence objects
  promoted into primary navigation without justification, one case
  fragmented across multiple equal-rank pages, new automation that adds
  attention surfaces without reducing operator work, noisy default
  surfaces with no action/watch/reference hierarchy, duplicate visible
  blocker/reason/next-action summaries, customer/operator default paths
  that expose raw JSON, fingerprints, reason ownership, platform reason
  families, or monitoring detail, helper actions such as `Open
  operation`, `Technical details`, or `Show JSON` competing with the
  dominant decision action, `Filament Costume`,
  `Blade Request UI`, `Hand-Rolled Simple Overview`, `Hidden Exception`,
  `Host Drift`, `State Layer Collapse`, `Parallel Inspect Worlds`, or
  undocumented exceptions without dedicated tests.

Guard tests
- Repository guards SHOULD validate: declared surface type, declared
  decision-role prominence where specs or metadata expose it,
  conformant primary inspect model, absence of redundant View actions,
  presence of explicit Inspect on Queue / Review and History / Audit
  surfaces, absence of empty `ActionGroup` or `BulkActionGroup`,
  correct placement of destructive actions, truthful scope signals,
  stable canonical nouns across shells, presence of a single dominant
  next action where surface metadata exposes one, absence of duplicate
  visible decision summaries, explicit raw/support gating or secondary
  placement where the surface serves multiple audience classes,
  absence of fake-native primary controls where metadata says the
  surface is native, bounded shared family contracts where metadata
  says a family is reused, explicit state ownership where specs or
  metadata expose it, and dedicated tests for every approved
  exception.

#### Immediate Retrofit Priorities

Wave 0 - Surface role classification
- First classify existing surfaces as Primary Decision, Secondary
  Context, or Tertiary Evidence / Diagnostics surfaces.
- For each surface, determine whether its current prominence is
  justified, which detail can move into progressive disclosure, and
  whether several technical pages should collapse into one decision
  context.
- Wave 0 is done only when primary navigation candidates are grounded
  in workflows rather than storage structures.

Wave 1 - Interaction normalization
- First fixes target redundant row click plus View, destructive row actions on standard lists, empty overflow or bulk groups, and rows that have become pseudo-control centers.
- First-slice focus surfaces are Tenants, Workspaces, Policies, Alert Deliveries, and other CRUD-first list surfaces with the same drift pattern.
- Wave 1 is done only when each surface has exactly one primary inspect model, destructive actions are protected, and placeholder groups are gone.

Wave 2 - Scope, nouns, and truth
- Then fix scope and context leaks, stabilize canonical nouns, make cross-panel transitions explicit, move critical operational truth to default-visible regions, and reduce prose-heavy dense rows.

Wave 3 - Enforcement
- Then move the constitution into repo enforcement, require the PR checklist, anchor guard tests, and trim old declaration-only action-surface checks until behavior is the governing truth.

#### Appendix A - One-page Condensed Constitution

- Every operator-facing surface declares one decision role:
  Primary Decision, Secondary Context, or Tertiary Evidence /
  Diagnostics.
- Primary surfaces exist to help a human prioritize, judge, approve,
  reject, escalate, or act.
- Evidence and diagnostics remain available but do not dominate the
  default workflow.
- Default to decisions, not details.
- Progressive disclosure preserves depth without forcing it into the
  first decision.
- Navigation follows workflows, not storage structures.
- One governance case should be decidable in one focused context.
- Automation must reduce attention load.
- Default surfaces stay calm, prioritized, and explicit about what is
  actionable, worth watching, and reference-only.
- Every new or materially changed surface declares one broad
  action-surface class first.
- Every admin surface has one surface type.
- Every list has exactly one primary inspect/open model.
- CRUD and Registry surfaces use one-click open.
- Queue and Audit surfaces use explicit Inspect.
- Edit-as-inspect exists only for Config-lite resources.
- Standard lists expose at most one inline safe shortcut.
- Destructive actions never sit openly beside inspect on standard lists.
- Overflow is standardized per surface class and is never empty.
- Bulk exists only when it is genuinely useful.
- Standard forms, filters, tables, tabs, badges, links, and simple
  overviews are native-by-default.
- Fake-native surfaces, hidden exceptions, host drift, and state-layer
  collapse do not ship.
- Repeated detail micro-UIs define shared core and bounded host
  variation before a second host forks them.
- Shell, page, and detail truth each have one owner.
- Navigation and mutation do not share equal visual weight without
  explicit hierarchy.
- Monitoring and workbench surfaces separate scope/context, selection,
  navigation, and object actions.
- Scope chips must be truthful.
- Domain nouns are canonical and stable.
- Critical operational truth is default-visible.
- Multi-audience detail/status surfaces keep customer-readable decision
  content above operator diagnostics and support/raw evidence.
- One dominant next action stays visually primary.
- Duplicate visible decision truth is forbidden.
- Semantic truth dimensions are not collapsed into a generic status.
- Standard lists stay scanable.
- Exceptions are catalogued, justified, and tested.
- Features with ambiguous interaction semantics do not ship.
- Header actions on record/detail pages expose at most one primary action; navigation belongs at context, not in the header.

#### Appendix B - Feature Review Checklist

- Decision-role prominence is declared.
- The human-in-the-loop moment is explicit.
- Immediate-visible decision information is explicit.
- On-demand evidence / diagnostics boundaries are explicit.
- Audience-aware default visibility and raw-evidence boundaries are
  explicit where the page serves more than one audience class.
- Any new primary surface is justified against an existing decision
  context.
- Navigation reflects a workflow rather than storage structure.
- One governance case stays decidable in one focused context.
- The feature reduces search, review, or click work.
- The resulting surface is calmer and clearer, not merely larger.
- Broad action-surface class is declared.
- Detailed surface type is declared.
- The one most likely next operator action is explicit.
- One dominant next action stays primary.
- Duplicate visible decision truth is absent.
- The surface is classified correctly as native, custom, or shared
  family.
- Primary inspect/open model is defined.
- Row-click rule is decided.
- View/Inspect is correctly present or correctly forbidden.
- Edit-as-inspect is used only when allowed.
- Fake-native shortcuts are absent or explicitly exception-gated.
- Shared-family core vs host-owned variation is explicit where relevant.
- Navigation and mutation are separated intentionally.
- Secondary actions are grouped correctly.
- Destructive actions are placed correctly.
- Overflow is not empty.
- Bulk is justified.
- Inline labels are short.
- Scope signals are truthful.
- Canonical nouns stay consistent.
- Critical truth is visible.
- Scanability is preserved.
- Shell, page, and detail state owners are explicit.
- Requested, active, draft, inspect, and restorable roles are explicit
  when the surface uses them.
- Exceptions are documented and tested.
- Header passes the 5-second scan rule (HDR-001).
- No pure navigation in the header.
- Governance-changing actions have extra friction.
- Any special type or workflow-hub exception is real and justified.

#### Appendix C - Red Flags for Future PRs

- A primary surface has no clear human-in-the-loop moment.
- A technical object hub is promoted into primary navigation without
  workflow justification.
- Default-visible content behaves like a diagnostics console instead of
  a decision surface.
- The operator must assemble one decision from multiple equal-rank Run,
  Evidence, Policy, Audit, or Finding pages.
- A feature adds automation, alerts, or statuses that increase net
  attention load.
- The surface creates more noise than priority.
- Row click and View open the same destination.
- A Filament-looking surface keeps its real primary contract in raw HTML,
  GET, or Blade request state.
- A simple overview is rebuilt as bespoke markup without a real product
  reason.
- A special surface exists only by history and lacks a named exception.
- A row becomes a control center.
- Archive or Delete sits openly beside View or Inspect on a standard list.
- More menus or bulk menus are empty.
- A More menu becomes a mixed junk drawer with no ordering logic.
- Scope chips have no real scope effect.
- Runs and Operations are used as competing primary collection nouns.
- Long workflow labels live in dense tables.
- Edit is used as default inspect even though a true View surface exists.
- Queue surfaces throw the operator out of context through row click.
- A workbench surface mixes scope, selection, navigation, and object
  actions as one flat header rail.
- Critical health or operability truth is hidden by default.
- A contract claims conformance while the rendered UI behaves differently.
- A repeated detail surface quietly changes family core structure from
  one host to another.
- Shell, page, and detail layers each claim the same truth.
- One concern has two competing inspect or view-state owners.
- Header has multiple equally weighted buttons without clear prioritization.
- "Open X" navigation links placed in the header instead of at the related field.
- Governance-changing actions sit casually beside the primary action without friction.

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

### Filament Native First / No Ad-hoc Styling (UI-FIL-001)
- Admin and operator-facing surfaces MUST use native Filament components, existing shared UI primitives, and centralized design patterns first.
- TenantPilot custom Filament UI MUST follow `docs/ui/tenantpilot-enterprise-ui-standards.md`. When this constitution gives a shorter rule, that document remains the canonical detailed standard for custom Filament affordance, styling, hierarchy, and disclosure patterns.
- If Filament already provides the required semantic element, feature code MUST use the Filament-native component instead of a locally assembled replacement.
- Preferred native elements include `x-filament::badge`, `x-filament::button`, `x-filament::icon`, and Filament Forms, Infolists, Tables, Sections, Tabs, Grids, and Actions.
- Local Blade/Tailwind cards are allowed only when they preserve dark
  mode correctness, spacing consistency, badge semantics, action
  hierarchy, progressive disclosure, accessibility, and overall
  Filament visual language.

Enterprise consistency for custom surfaces
- TenantPilot custom Blade, Livewire widget, Filament page, and
  productized dashboard/detail surfaces MUST preserve Filament-native
  interaction semantics unless the governing spec records a bounded
  product reason to diverge.
- Custom surfaces MUST NOT introduce independent button systems,
  status color semantics, spacing systems, or card styles that
  function as a parallel local design system.
- Feature specs and implementation MUST NOT introduce ad-hoc custom
  styling for cards, buttons, hovers, badges, icons, progress bars,
  empty states, or interactive rows.
- Each page, card cluster, or other focused action area MUST keep at
  most one dominant primary action. Secondary actions MUST remain
  neutral unless the action is destructive or the semantic state
  change is itself the point of the action.
- Status, health, risk, readiness, and similar state cues MUST be
  conveyed through BADGE-001 badges, labels, chips, and supporting
  text rather than arbitrary button colors or per-card custom action
  styling.
- Hover, pointer, focus, shadow, or similar interactive affordance MUST
  appear only when a repo-real route/action exists and the current
  actor has the permitted capability. Otherwise the surface MUST render
  as static and non-interactive.
- Custom Blade/Tailwind composition MUST be used to arrange
  product-specific layout, decision hierarchy, and progressive
  disclosure, not to redefine semantic action, status, or container
  primitives that Filament or shared project primitives already
  standardize.
- Per-card custom action styling, status-colored non-status actions,
  and oversized custom borders, shadows, or spacing that visually
  detach a surface from the Filament panel are forbidden unless
  UI-EX-001 records a bounded exception.

Native-by-default classification
- `Native Surface` means the primary interaction contract is built from
  Filament-native components or approved shared primitives.
- Standard forms, filters, tables, tabs, badges, links, and simple
  overviews default to `Native Surface` status.
- `Custom Surface` is allowed only through UI-EX-001 when the operator
  need is richer than standard CRUD, overview, or report semantics.
- `Fake-Native Surface` is forbidden: a surface that looks native but
  keeps a second HTML, GET, query, or Blade-request contract for the
  same primary interaction.

Forbidden local replacements
- Feature code MUST NOT hand-build badges, pills, status chips, alert cards, or action buttons from raw `<span>`, `<div>`, or `<button>` markup plus Tailwind classes when Filament-native or shared project primitives can express the same meaning.
- Feature code MUST NOT introduce page-local visual status languages for status, risk, outcome, drift, trust, importance, or severity.
- Feature code MUST NOT make local color, border, rounding, or emphasis decisions for semantic UI states using ad-hoc classes such as `bg-danger-100`, `text-warning-900`, `border-dashed`, or `rounded-full` when the same state can be expressed through Filament props or shared primitives.
- `Filament Costume` is forbidden: locally assembled markup that merely
  imitates native Filament controls, badges, or actions.
- `Blade Request UI` is forbidden: request-driven body state or GET-form
  control rails as the primary interaction contract inside an active
  Filament surface.
- `Hand-Rolled Simple Overview` is forbidden: bespoke overview/report
  shells where a native table/list surface fits the job.

Shared primitive before local override
- If the same UI pattern can recur, it MUST use an existing shared primitive or introduce a new central primitive instead of reassembling the pattern inside a Blade view.
- Central badge and status catalogs remain the canonical source for status semantics; local views MUST consume them rather than re-map them.
- If the same custom detail, evidence, or review surface appears in
  more than one host, it becomes a `Shared Detail Micro-UI` and MUST
  define shared core vs host variation before another host reassembles
  it locally.
- Local one-off markup MUST NOT recreate decision/diagnostics/raw
  layering when an existing shared detail family is sufficient.

Upgrade-safe preference
- Update-safe, framework-native implementations take priority over page-local styling shortcuts.
- Filament props such as `color`, `icon`, and standard component composition are the default mechanism for semantic emphasis.
- Publishing or emulating Filament internals for cosmetic speed is not acceptable when native composition or shared primitives are sufficient.

Exception rule
- Ad-hoc markup or styling is allowed only when all of the following are true:
  - native Filament components cannot express the required semantics,
  - no suitable shared primitive exists,
  - and the deviation is justified briefly in code and in the governing spec or PR.
- Approved exceptions MUST stay layout-neutral, use the minimum local
  classes necessary, MUST NOT invent a new page-local status language,
  MUST preserve dark mode correctness, spacing consistency,
  badge semantics, action hierarchy, progressive disclosure,
  accessibility, and MUST say what remains standardized.
- `Hidden Exception` is forbidden. Historical accident or local
  implementation convenience is not a valid substitute for UI-EX-001.

Review and enforcement
- Every UI review MUST answer:
  - which native Filament element or shared primitive was used,
  - why an existing component was insufficient if an exception was taken,
  - whether the surface is native, custom, or a shared detail family,
  - whether any local Blade/Tailwind card still preserves Filament
    visual language and disclosure semantics,
  - and whether any ad-hoc status, emphasis styling, or fake-native
    contract was introduced.
- UI work is not Done if it introduces ad-hoc status styling or framework-foreign replacement components where a native Filament or shared UI solution was viable.

### Incremental UI Standards Enforcement (UI-STD-001)
- UI consistency is enforced incrementally, not by recurring cleanup passes.
- New tables, filters, and list surfaces MUST follow established Filament-native standards from the first implementation.
- Deviations MUST be explicit and justified in the spec or PR.
- Canonical standards live in `docs/product/standards/` and are the source of truth for:
  - Table UX (column tiers, sort, search, toggle, pagination, persistence, empty states)
  - Filter UX (persistence, soft-delete, date range, enum sourcing, defaults)
  - Actions UX (row/bulk/header actions, grouping, destructive safety)
- Guard tests enforce critical constraints automatically; the list surface review checklist catches the rest.
- A new spec that adds or modifies a list surface MUST reference the review checklist (`docs/product/standards/list-surface-review-checklist.md`).

### 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 ...`.
- Runtime changes MUST validate the narrowest relevant lane and document any material budget, baseline, or trend follow-up in the active spec or PR.
- Run `./vendor/bin/sail bin pint --dirty` before finalizing.

## Governance

### Scope, Compliance, and Review Expectations
- 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.
- Specs and PRs that introduce new persisted truth, abstractions, states, DTO/presenter layers, or taxonomies MUST include the proportionality review required by BLOAT-001.
- Runtime-changing or test-affecting specs and PRs MUST include testing/lane/runtime impact covering actual test-purpose classification, affected lanes, fixture/helper/factory/seed/context cost changes, any heavy-family expansion, expected budget/baseline/trend effect, escalation decisions, and the minimal validation commands.
- Specs, plans, task lists, and review checklists MUST surface the test-governance questions needed to catch lane drift, hidden defaults, and runtime-cost escalation before merge.
- Specs and PRs that touch shared provider/platform seams MUST classify the touched boundary as provider-owned or platform-core, keep provider-specific semantics out of platform-core contracts and vocabulary unless explicitly justified, and record whether any remaining hotspot is resolved in-feature or escalated as a follow-up spec.
- Specs and PRs that create, queue, deduplicate, resume, block, complete, or deep-link to an `OperationRun` MUST reuse the
  central OperationRun Start UX Contract, keep queued DB notifications explicit opt-in unless the active spec states a
  different policy, route terminal notifications through the lifecycle mechanism, include an `OperationRun UX Impact`
  section in the active spec or plan, and document any temporary exception with an architecture note, test rationale,
  and migration decision.
- Specs and PRs that change detail or status surfaces MUST explicitly
  document how they satisfy customer-readable decision-first content,
  diagnostics-secondary disclosure, support/raw-evidence gating, one
  dominant next action, duplicate-truth prevention, and shared-pattern
  reuse.
- Specs and PRs that change operator-facing surfaces MUST classify each
  affected surface under DECIDE-001 and justify any new Primary
  Decision Surface or workflow-first navigation change.
- Reviews MUST reject runtime or test changes when lane classification is missing, fast-lane work quietly absorbs heavy cost, expensive defaults are introduced silently, or material CI/runtime drift is left undocumented.
- Review and approval MUST favor simplification, replacement, and absorption over additive semantic layering.
- Future-release preparation alone is not sufficient justification for new persistence or frameworkization unless security, tenant isolation, auditability, compliance evidence, or queue correctness already require it.

### 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**: 2.13.0 | **Ratified**: 2026-01-03 | **Last Amended**: 2026-05-03
