TenantAtlas/specs/201-enforcement-review-guardrails/research.md
ahmido 15b21c3080
Some checks failed
Main Confidence / confidence (push) Failing after 44s
spec: finalize enforcement review guardrails workflow (#250)
## Summary
- add the full Spec 201 artifact set for enforcement and review guardrails
- update the SpecKit workflow surfaces to carry UI/surface guardrail classification, handling modes, proof depth, and close-out targeting
- align the operator UX standards reference and agent context with the new guardrail workflow

## Validation
- completed cross-artifact consistency analysis for spec, plan, tasks, research, data model, contracts, and quickstart
- recorded the low-impact workflow path at `00:48` and the representative guarded review at `02:34`
- no Pest or runtime test suite was run because this is a docs/workflow-only feature
- integrated browser smoke on the tenant dashboard could not complete because tenant-scoped unauthenticated navigation currently redirects to `/admin/t/login`, which returns `404 Not Found`

## Filament Notes
- Livewire v4.0+ compliance is unchanged
- provider registration remains in `bootstrap/providers.php`
- no globally searchable resources were added or modified
- no destructive runtime actions were introduced or changed
- no asset strategy changes were made; existing `filament:assets` deployment behavior remains unchanged

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #250
2026-04-18 22:46:06 +00:00

115 lines
12 KiB
Markdown

# Research: Enforcement & Review Guardrails
## Decision 1: Keep Spec 200 and the constitution as the only normative rule source
- **Decision**: Treat Spec 200 and `.specify/memory/constitution.md` as the source of truth for UI and surface rules, and use Spec 201 only to operationalize those rules through workflow artifacts.
- **Rationale**: Spec 201 exists to make the existing rules early-visible and reviewable, not to restate or replace them. Reopening the constitution as a second rule-writing exercise would recreate the same split-source problem this feature is meant to solve.
- **Alternatives considered**:
- Add a new top-level guardrail rulebook: rejected because it would force reviewers to reconcile two overlapping authorities.
- Keep guardrails only in feature-local docs: rejected because the workflow would then lack shared authoring and review touchpoints.
## Decision 2: Reuse the existing SpecKit workflow surfaces instead of creating a new process
- **Decision**: Put the operational changes into `.specify/templates/spec-template.md`, `.specify/templates/plan-template.md`, `.specify/templates/tasks-template.md`, `.specify/templates/checklist-template.md`, and `.specify/README.md`.
- **Rationale**: These are the surfaces contributors already use when drafting, planning, tasking, and reviewing feature work. Tightening them creates leverage where decisions are already made, without adding another process entry point.
- **Alternatives considered**:
- Create a new dedicated handbook under `docs/`: rejected because it would be easier to ignore and harder to keep in sync with the live workflow.
- Put all guidance only into `.specify/memory/constitution.md`: rejected because authors and reviewers need operational prompts where they already work, not just high-level rules.
## Decision 3: Keep first-pass repository signals report-first and exception-aware
- **Decision**: Model technical signals as report-only, review-mandatory, exception-required, or future hard-stop candidates, but do not introduce automatic hard CI blocking in the first pass.
- **Rationale**: Several anti-patterns are grep-able, but legitimate custom surfaces and bounded exceptions still require human judgment. The first operational layer should make likely drift visible early without making the repo noisy or brittle.
- **Alternatives considered**:
- Immediate CI failures for all grep-detectable patterns: rejected because false positives would be too high before the exception path and vocabulary are stabilized.
- Purely narrative guidance with no signal catalog: rejected because authors and reviewers need concrete early-warning patterns, not only abstract rules.
## Decision 4: Separate guardrail classes from handling modes
- **Decision**: Distinguish the class of a guardrail problem from how it is handled. The stable classes are review guardrails, repository signals, test guardrails, exception workflows, and workflow touchpoints; the handling modes are hard-stop candidate, review-mandatory, exception-required, and report-only.
- **Rationale**: The same product rule can show up in multiple operational ways. For example, a fake-native case is both a review question and a technical signal, while a special visualization may be review-mandatory and exception-required but never grep-detectable. Separating class from handling mode keeps the vocabulary stable.
- **Alternatives considered**:
- Collapse class and handling into one flat list: rejected because it would blur the difference between “what kind of problem is this?” and “how should the workflow react?”
- Use only blocker versus non-blocker: rejected because the spec explicitly needs finer distinctions for exceptions and future hardening.
## Decision 5: Model required test depth by surface contract class, not by technology alone
- **Decision**: Drive test-guardrail requirements from the surface contract class: shared detail family, monitoring/governance page with its own state contract, global context shell surface, exception-coded custom surface, or standard native Filament surface.
- **Rationale**: The testing requirement is about interaction and state risk, not just whether the surface uses Filament, Blade, or Livewire. This keeps test depth proportional and avoids forcing bespoke tests onto ordinary standard surfaces.
- **Alternatives considered**:
- Require extra tests for every Filament change: rejected because it would create friction without better risk discrimination.
- Leave test depth fully discretionary: rejected because the spec explicitly requires required-test signals for certain surface classes.
## Decision 6: Keep the exception workflow explicit and spread-sensitive
- **Decision**: Require each exception to name the broken or relaxed rule, the product reason, the boundary, the standardized parts that remain, and the spread-control rule that prevents silent extension to new hosts or surfaces.
- **Rationale**: Hidden exceptions are one of the target problem classes. The workflow must make “one-off but allowed” visibly different from “new precedent by drift.”
- **Alternatives considered**:
- Let each spec describe its exception informally: rejected because that would recreate the hidden-exception pattern.
- Ban most exceptions outright: rejected because legitimate special visualizations and bounded state exceptions are already part of the intended product model.
## Decision 7: Use logical contracts for the guardrail pack, not runtime APIs
- **Decision**: Create a JSON Schema and a logical OpenAPI file under `contracts/` that describe the planning-time guardrail pack and its workflow semantics.
- **Rationale**: Adjacent governance specs already use structured contract artifacts to make non-runtime workflow truth explicit. Reusing that pattern keeps planning artifacts consistent and gives future task generation a concrete model.
- **Alternatives considered**:
- Markdown-only notes in `contracts/`: rejected because they are less structured for downstream use.
- Real HTTP or CLI API contracts: rejected because this feature does not introduce a runtime service.
## Decision 8: Keep operator-UX standards as a secondary alignment document only
- **Decision**: Treat `docs/ui/operator-ux-surface-standards.md` as a reference-only alignment target and touch it only if one minimal cross-reference is needed.
- **Rationale**: The workflow changes belong in `.specify/` and the feature-local artifacts. Duplicating them into operator-UX standards would reintroduce drift between rule source, workflow, and supporting prose.
- **Alternatives considered**:
- Expand the operator-UX standards doc with full guardrail mechanics: rejected because it would become a second operational handbook.
- Ignore the doc entirely: rejected because a minimal pointer may still be needed to keep terminology aligned.
## Decision 9: Validate both low-friction and high-risk paths
- **Decision**: Validate the workflow against one low-impact docs-only scenario and multiple high-risk representative cases grounded in Specs 196 through 200.
- **Rationale**: The low-impact scenario proves the workflow does not overharden ordinary documentation changes. The representative drift cases prove that the new prompts and checklist language can classify the problem classes the feature is meant to stop.
- **Alternatives considered**:
- Validate only a high-risk case: rejected because it would not prove that the low-impact path stays lightweight.
- Validate only hypothetical examples: rejected because the repo already has real cases and vocabulary anchors that should be reused.
## Validation Scenario Set
| Scenario | Source artifact | Expected guardrail result |
|---|---|---|
| Low-impact docs-only workflow change | `.specify/templates/checklist-template.md` and `.specify/README.md` | `N/A` path remains acceptable, no fake runtime obligations, explicit `keep` outcome remains possible |
| Fake-native hard-signal case | `specs/196-hard-filament-nativity-cleanup/` | hard technical signal and blocker unless a bounded exception exists |
| Shared-family host-drift case | `specs/197-shared-detail-contract/` | review-mandatory classification with host/core boundary check and exception spread control |
| State-layer confusion case | `specs/198-monitoring-page-state/` and `specs/199-global-context-shell-contract/` | review-mandatory classification that names shell/page/detail ownership explicitly |
| Legitimate special-case surface | `specs/200-filament-surface-rules/` representative exception model | documentation-required exception rather than default violation |
## Implementation Adjustment Note
- The narrowest rollout for Spec 201 is feature-local guardrail design plus workflow-surface updates. It should not pull in runtime code, root-level onboarding docs, or CI policy unless the implementation proves that a smaller workflow surface is insufficient.
## Canonical Repository Signal Catalog
| Signal ID | Problem class | First-pass handling mode | Exception / review path | Future promotion rule |
|---|---|---|---|---|
| `SIG-001` | Fake-native control or page-body interaction disguised as native Filament behavior | `hard-stop-candidate` | Named bounded exception only; otherwise reviewer stops the change | Eligible for hard CI blocking only after report-first use stays low-noise across real repo cases |
| `SIG-002` | GET-form or request-driven page-body state outside the documented shell or list/filter contract | `review-mandatory` | Review must classify whether the state belongs to shell, page, detail, or URL/query ownership | Promote only if future false positives stay low and the state-owner vocabulary remains stable |
| `SIG-003` | Shared-family host fork or duplicate partial drift | `review-mandatory` | Fold back into the shared contract or document a bounded host exception with spread control | Future linting is deferred until the shared-family boundaries remain stable across multiple cases |
| `SIG-004` | Shell or context resolution logic leaking into presentation partials or page-local helpers | `review-mandatory` | Review must prove shell ownership and keep page/detail surfaces from becoming hidden context engines | Stay report-first until the repo has a proven shell regression pattern worth hardening |
| `SIG-005` | Hand-rolled simple overview or status UI where native Filament widgets or shared primitives should remain primary | `report-only` | Review decides whether this is a real special visualization or just avoidable custom surface drift | Never hard-stop automatically without a later spec proving the false-positive rate is acceptably low |
## Canonical Test Guardrail Matrix
| Surface class | Trigger | Required proof types | Manual smoke expectation | Relief rule |
|---|---|---|---|---|
| `standard-native-filament` | Standard Resource/Page/RelationManager work with no special shared-family, shell, or exception contract | Ordinary feature coverage only | Optional normal UI smoke only | This is the explicit relief rule: no extra bespoke guardrail proof is required |
| `shared-detail-family` | Reused detail micro-UI or host/core contract shared across multiple surfaces | `functional-core` | Verify host/core boundaries and one representative host rendering | Add exception coverage only if a host intentionally diverges |
| `monitoring-state-page` | Monitoring/governance page with its own state contract | `functional-core`, `state-contract` | Verify empty, loaded, and conflict states remain legible | Use the narrowest honest lane; no browser expansion by default |
| `global-context-shell` | Shared shell or context-recovery surface | `state-contract`, `exception-fallback` | Verify valid scope, invalid scope, and recovery/fallback clarity | Manual smoke stays required because shell truth crosses many pages |
| `exception-coded-surface` | Legitimate custom or special visualization that relaxes a default rule | `functional-core`, `exception-fallback` | Verify the bounded exception and the preserved standardized parts | Close-out must explain why `standard-native-filament` relief does not apply |
## First-Pass Automation Deferrals
- Grep or lint rules for `SIG-001` through `SIG-005` stay report-first only; no CI hard-stop is introduced in this rollout.
- No PR bot or generated comment is added to enforce the active feature PR close-out entry.
- No repo-wide scanner auto-detects shared-family host forks until false-positive escape paths are proven in practice.
- No automatic promotion from `review-mandatory` to blocking occurs without a later spec that reviews noise, misses, and ownership burden explicitly.