359 lines
40 KiB
Markdown
359 lines
40 KiB
Markdown
# Feature Specification: Spec 424 - Security Defaults Content-Backed Comparable Support
|
|
|
|
**Feature Branch**: `424-security-defaults-content-backed-comparable-support`
|
|
**Created**: 2026-06-30
|
|
**Status**: Draft
|
|
**Input**: User-provided draft "Spec 424 - Security Defaults Content-Backed Comparable Support", prepared through `spec-kit-next-best-prep`.
|
|
|
|
## Preparation Metadata
|
|
|
|
- **Selected candidate**: Spec 424 - Security Defaults Content-Backed Comparable Support.
|
|
- **Source location**: User attachment `/Users/ahmeddarrazi/.codex/attachments/5bd37778-05ff-4b65-b5fc-407deb4d5000/pasted-text.txt`.
|
|
- **Why selected**: The active auto-prep queue in `docs/product/spec-candidates.md` remains empty, but the user explicitly promoted this bounded Coverage v2 follow-up. Spec 421 proved Conditional Access comparable/renderable support and deferred Security Defaults because it was not content-backed. Spec 423 is now completed, leaving Security Defaults as the precise Entra denominator blocker before any later certified Entra compare pack can be credible.
|
|
- **Roadmap relationship**: Aligns with the roadmap's Microsoft governance expansion, evidence/coverage hardening, provider-boundary discipline, and security posture direction. This package is not auto-selected from the candidate queue; it is a user-promoted P0 Coverage v2 safety slice.
|
|
- **Close alternatives deferred**: Management-report runtime validation, governance artifact lifecycle retention, provider readiness productization, cross-domain indicator follow-through, system-panel browser fixture work, and first governed AI consumer remain manual-promotion backlog items. Entra certification, restore/apply, customer reports, Review Pack output, full Entra coverage, and additional Entra resource types remain later explicit specs.
|
|
- **Related completed-spec guardrail**: `specs/414-tcm-first-coverage-core-cutover/`, `specs/415-generic-content-backed-capture/`, `specs/417-canonical-identity-engine/`, `specs/418-coverage-v2-operator-surface/`, `specs/419-m365-tcm-workload-registry-expansion/`, `specs/420-m365-generic-evidence-coverage-pack/`, `specs/421-entra-core-comparable-renderable-pack/`, and `specs/423-security-compliance-readiness-pack/` contain completed/validated signals and are read-only dependency context. Do not rewrite them, normalize their close-out history, or strip task/browser/review evidence.
|
|
- **Repo-truth preflight result**: Current code has a `securityDefaults` registry row in `ResourceTypeRegistry::m365RepresentativeDefinitions()`, but it is registry-only/out-of-scope, uses existing `source_class = tcm`, has `default_coverage_level = detected`, `default_evidence_state = not_captured`, `default_claim_state = internal_only`, and `restore_tier = not_restorable`. `CoverageSourceContractResolver` has no `securityDefaults` mapping, `config/graph_contracts.php` has no Security Defaults contract, `CoverageIdentityStrategyRegistry` has no `securityDefaults` strategy, and `EntraComparablePayloadNormalizer` supports only `conditionalAccessPolicy`. `SupportedScopeResolver` includes `securityDefaults` in Entra planning scope, but no certified or restore-ready Security Defaults scope may be activated in this spec.
|
|
- **Smallest viable implementation slice**: Add the minimum repo-conventional source contract, capture eligibility, singleton-safe evidence capture proof, identity strategy, typed normalizer, comparator, render summary, Claim Guard hardening, redaction proof, RBAC/scope proof, and tests needed to promote only `securityDefaults` to internal/operator content-backed, comparable, and renderable support. If the source contract cannot be proven safely, the implementation must leave Security Defaults blocked with a stable missing-contract/unsupported result and must not promote support.
|
|
- **Candidate Selection Gate**: PASS for a direct user-provided P0 candidate with repo-truth deviations documented below.
|
|
|
|
## Draft-To-Repo Deviations
|
|
|
|
- The draft uses `restore_tier = compare_only`; current repo truth has `not_restorable`, `preview_only`, and `restorable`. This spec uses `not_restorable` as the repo-equivalent no-restore posture and forbids adding a new restore tier unless the proportionality review is amended.
|
|
- The draft allows `resource_class = security_setting` or `tenant_setting`; current repo truth has `ResourceClass::Configuration`. This spec keeps `configuration` unless implementation proves a new resource class has a current-release behavioral consequence and amends the proportionality review first.
|
|
- The draft lists `capture_blocked_source_unavailable`; current repo outcomes are `captured`, `capture_blocked_missing_contract`, `capture_blocked_permission`, `capture_blocked_beta`, `capture_blocked_unsupported`, and `capture_failed`. This spec uses existing outcomes plus stable reason codes unless a new outcome passes the constitution proportionality gate.
|
|
- The draft allows source class `tcm` or `graph_v1_fallback`. Current repo truth has `securityDefaults` seeded as a TCM planning row but no real contract. Implementation may switch the row to `graph_v1_fallback` only if the canonical graph contract and capture path prove a real v1 content source. It must not promote a beta-only source to later-certifiable support.
|
|
|
|
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
|
|
|
|
- **Problem**: Security Defaults is part of the later Entra certified compare denominator, but TenantPilot currently treats `securityDefaults` as registry-only/out-of-scope and cannot capture, compare, or render it as content-backed evidence.
|
|
- **Today's failure**: A later Entra compare claim would either omit a core security setting or imply Security Defaults support that repo truth does not prove. Operators cannot answer whether Security Defaults is enabled without raw provider inspection or unsafe overclaim.
|
|
- **User-visible improvement**: Authorized internal operators can see Security Defaults as content-backed, comparable, and renderable on the existing Coverage v2 path once real evidence exists, while certification, restore, customer-ready, and full Entra claims remain blocked.
|
|
- **Smallest enterprise-capable version**: Support exactly `securityDefaults` through existing Coverage v2 capture/evidence/identity/redaction/Claim Guard/read-model paths. No new Entra dashboard, no restore, no certification, no customer output, no additional Entra types.
|
|
- **Explicit non-goals**: No Entra certification, no restore/apply, no Review Pack/report/PDF/export output, no customer-facing Entra claim, no Application/Service Principal/Role Definition/Administrative Unit support, no new Entra table family, no separate Security Defaults engine, no live docs fetch, no `tenant_id`, no v1 compatibility.
|
|
- **Permanent complexity imported**: One focused source contract mapping if safe, one bounded identity strategy, Security Defaults typed normalization/compare/render helper extensions or sibling helpers, Claim Guard phrase coverage, redaction tests, and focused feature/browser-if-rendered tests. No new persisted entity, broad status family, route, dashboard, or cross-domain framework is planned.
|
|
- **Why now**: Spec 421 proved Conditional Access comparable/renderable support and deferred Security Defaults. Security Defaults is the next concrete blocker before any later Entra denominator can be certified or described honestly.
|
|
- **Why not local**: A local Security Defaults parser or ad-hoc Graph call would bypass Coverage v2 source contracts, evidence persistence, provider scope, identity, redaction, OperationRun, and Claim Guard truth. The existing Coverage v2 path is the narrowest correct implementation.
|
|
- **Approval class**: Core Enterprise.
|
|
- **Red flags triggered**: Adds typed support and source-contract mapping for one provider-specific singleton. Defense: the slice is limited to one concrete security setting, plugs into existing Coverage v2 machinery, and prevents a concrete future overclaim.
|
|
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 1 | Produktnaehe: 2 | Wiederverwendung: 2 | **Gesamt: 11/12**
|
|
- **Decision**: approve as a narrow, evidence-gated support closure.
|
|
|
|
## Spec Scope Fields *(mandatory)*
|
|
|
|
- **Scope**: workspace plus managed-environment scoped Coverage v2 evidence for one Entra resource type, `securityDefaults`.
|
|
- **Primary Routes**: Existing internal/operator Coverage v2 readiness/inspect route only if rendered data changes. No new route, navigation entry, customer route, report, download, dashboard, wizard, or action is in scope.
|
|
- **Data Ownership**: Existing Coverage v2 `TenantConfigurationResourceType`, `TenantConfigurationResource`, and `TenantConfigurationResourceEvidence` rows remain owned by `workspace_id`, `managed_environment_id`, and same-scope `provider_connection_id` for provider-sourced records. Provider-native Microsoft tenant IDs remain metadata only.
|
|
- **RBAC**: Existing Coverage v2 read authorization applies. Non-member or wrong workspace/environment access is deny-as-not-found (404). A member missing the required view capability receives 403. Capture start permissions remain existing tenant-configuration capture permissions; readonly users must not start capture.
|
|
|
|
## No Legacy / No Backward Compatibility Constraint *(mandatory)*
|
|
|
|
TenantPilot is pre-production for this feature.
|
|
|
|
- **Compatibility posture**: canonical Coverage v2 extension.
|
|
- **Legacy aliases, fallback readers, hidden routes, duplicate UI, old labels, or historical fixtures kept?**: no.
|
|
- **Why clean replacement is safe now**: This is a new support closure over Coverage v2. No customer contract requires Coverage v1 adapters, dual writes, fallback readers, legacy claim labels, or old fixture preservation.
|
|
|
|
## UI Surface Impact *(mandatory - UI-COV-001)*
|
|
|
|
Does this spec add, remove, rename, or materially change any reachable UI surface?
|
|
|
|
- [ ] No UI surface impact
|
|
- [x] Existing page changed
|
|
- [ ] New page/route added
|
|
- [ ] Navigation changed
|
|
- [ ] Filament panel/provider surface changed
|
|
- [ ] New modal/drawer/wizard/action added
|
|
- [ ] New table/form/state added
|
|
- [ ] Customer-facing surface changed
|
|
- [ ] Dangerous action changed
|
|
- [x] Status/evidence/review presentation changed
|
|
- [ ] Workspace/environment context presentation changed
|
|
|
|
Expected impact is data-driven presentation on the existing Coverage v2 internal/operator readiness and inspect surface when Security Defaults comparable/renderable summaries become visible through existing read-model output. No new UI files are required by this spec. If implementation needs Blade, Livewire, Filament Resource/Page/Widget, route, navigation, action, or other runtime UI file edits, the plan/tasks must be amended first with the exact affected files, browser proof, and Human Product Sanity criteria.
|
|
|
|
## UI/Productization Coverage *(mandatory when UI Surface Impact is not "No UI surface impact")*
|
|
|
|
- **Route/page/surface**: Existing Coverage v2 readiness/resource/evidence inspection surface and inspect detail disclosure.
|
|
- **Current or new page archetype**: Technical Annex / read-only evidence inspection.
|
|
- **Design depth**: Internal/Hidden with Product Surface proof if rendered output changes.
|
|
- **Repo-truth level**: repo-verified existing surface from Spec 418.
|
|
- **Existing pattern reused**: Existing Coverage v2 read model, internal/operator inspect flow, badge/status patterns, and Spec 421 Entra render/compare family.
|
|
- **New pattern required**: none.
|
|
- **Screenshot required**: no standalone screenshot artifact required by prep; focused browser proof required if rendered output changes.
|
|
- **Page audit required**: no full page audit; focused existing-surface browser smoke is sufficient unless implementation changes runtime UI files, routes, navigation, page structure, actions, or panel/provider surface.
|
|
- **Customer-safe review required**: yes for wording boundaries; no customer route or output may be activated.
|
|
- **Dangerous-action review required**: no mutating/destructive action is in scope.
|
|
- **Coverage files updated or explicitly not needed**:
|
|
- [ ] `docs/ui-ux-enterprise-audit/route-inventory.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/design-coverage-matrix.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/page-reports/...`
|
|
- [ ] `docs/ui-ux-enterprise-audit/strategic-surfaces.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/grouped-follow-up-candidates.md`
|
|
- [ ] `docs/ui-ux-enterprise-audit/unresolved-pages.md`
|
|
- [x] `N/A - existing internal surface only; update coverage artifacts only if runtime UI files/routes/navigation change`
|
|
- **No-impact rationale when applicable**: N/A.
|
|
|
|
## Product Surface Impact *(mandatory for UI-affecting specs)*
|
|
|
|
Reference: `docs/product/standards/product-surface-contract.md`.
|
|
|
|
- **Product Surface Contract applies?**: yes, for data-driven rendered status/evidence/readiness changes on the existing Coverage v2 surface.
|
|
- **Page archetype**: Technical Annex.
|
|
- **Primary user question**: Is Security Defaults content-backed, comparable, renderable, and safe for later certification inclusion?
|
|
- **Primary action**: Inspect.
|
|
- **Surface budget result**: pass if limited to the existing read-only surface and inspect disclosure; exception required if implementation adds a new page, dashboard, action, customer output, or more than one primary decision flow.
|
|
- **Technical Annex / deep-link demotion**: Raw payloads, normalized JSON, source IDs, provider IDs, evidence hashes, OperationRun links, permission context, source contract keys, and unsupported fields remain hidden, demoted, or diagnostics-only.
|
|
- **Canonical status vocabulary**: Product-facing labels must use existing canonical states such as `Ready`, `Needs attention`, `Blocked`, and `Unknown`, or existing internal Coverage v2 labels. Do not expose `certified`, `restore-ready`, `customer-ready`, `full Entra coverage`, or `M365 certified`.
|
|
- **Visible complexity impact**: neutral or decreased if the existing inspect surface gains a concise summary; increased complexity requires a documented exception.
|
|
- **Product Surface exceptions**: none planned.
|
|
|
|
## Browser Verification Plan *(mandatory)*
|
|
|
|
- **Browser proof required?**: yes if Security Defaults summaries, comparable/renderable state, or readiness text render on the existing Coverage v2 surface; otherwise no.
|
|
- **No-browser rationale**: `N/A - no rendered UI surface changed` only if implementation proves no rendered output changes.
|
|
- **Focused path when required**: Existing Coverage v2 readiness/operator route with a seeded workspace, managed environment, provider connection, and Security Defaults content-backed evidence row.
|
|
- **Primary interaction to execute**: Load the existing route as an authorized operator, inspect the Security Defaults row, verify enabled/disabled/unknown summary, comparable/renderable state, no raw payload, no secrets, no certified/restore/customer claim, and no console/Livewire/Filament errors.
|
|
- **Console, Livewire, Filament, network, and 500-error checks**: planned when browser proof is required.
|
|
- **Full-suite failure triage**: unrelated browser/full-suite failures may be documented only after focused proof is green.
|
|
|
|
## Human Product Sanity Check *(mandatory)*
|
|
|
|
- **Required?**: yes if rendered output changes; no if no rendered output changes.
|
|
- **No-human-sanity rationale**: N/A only with exact no-rendered-change proof.
|
|
- **Reviewer questions**: Can an operator tell whether Security Defaults is enabled? Is it clear this is internal comparable/renderable support, not certification or restore readiness? Are technical details demoted? Is there one dominant inspect action? Is visible complexity not worse?
|
|
- **Planned result location**: implementation report / PR close-out.
|
|
|
|
## Product Surface Merge Gate Checklist *(mandatory)*
|
|
|
|
- [x] No-legacy posture or approved exception recorded.
|
|
- [x] Product Surface Impact is completed.
|
|
- [x] Browser proof is required if rendered output changes, or `N/A - no rendered UI surface changed` must be justified.
|
|
- [x] Human Product Sanity is required if rendered output changes, or N/A must be justified.
|
|
- [x] Product Surface exceptions are documented or `none`.
|
|
- [x] Implementation report will state Livewire v4 compliance, provider registration location, global search posture, destructive/high-impact action posture, asset strategy, tests/browser result, deployment impact, visible complexity outcome, and no completed-spec rewrite assertion.
|
|
|
|
## Cross-Cutting / Shared Pattern Reuse *(mandatory)*
|
|
|
|
- **Cross-cutting feature?**: yes.
|
|
- **Interaction class(es)**: source contract, evidence capture, typed compare/render, status/evidence presentation, claim safety.
|
|
- **Systems touched**: `ResourceTypeRegistry`, `CoverageSourceContractResolver`, `config/graph_contracts.php`, `GenericContentEvidenceCaptureService`, `CoverageIdentityStrategyRegistry`, `CanonicalIdentityResolver`, `EntraComparablePayloadNormalizer`, `EntraCoverageComparator`, `EntraRenderableSummaryBuilder`, `CoverageV2ReadinessReadModel`, `CoveragePayloadRedactor`, and `ClaimGuard`.
|
|
- **Existing pattern(s) to extend**: Spec 415 generic content-backed capture, Spec 417 canonical identity, Spec 421 Entra comparable/renderable helpers, existing Coverage v2 read model, existing Claim Guard.
|
|
- **Shared contract / presenter / builder / renderer to reuse**: Coverage v2 source/evidence/identity/read-model path, redactor, Claim Guard, and Entra comparable/renderable family.
|
|
- **Why the existing shared path is sufficient or insufficient**: Sufficient as the integration boundary. It lacks only Security Defaults source mapping, identity strategy, typed semantics, and claim phrase coverage.
|
|
- **Allowed deviation and why**: A focused singleton handling path is allowed only if the existing list capture path cannot safely capture the source payload; it must remain inside the existing Coverage v2 capture/source contract machinery.
|
|
- **Consistency impact**: Security Defaults support must align with existing coverage levels, evidence states, identity states, capture outcomes, claim states, redaction, RBAC behavior, and Product Surface demotion.
|
|
- **Review focus**: Verify no endpoint guessing, no direct HTTP/Graph SDK bypass, no raw payload default display, no customer claims, no restore/certify action, no mini-platform, no new tables, and no `tenant_id`.
|
|
|
|
## OperationRun UX Impact *(mandatory when touched)*
|
|
|
|
- **Touches OperationRun start/completion/link UX?**: no new start/completion/link UX.
|
|
- **Shared OperationRun UX contract/layer reused**: Existing tenant-configuration capture OperationRun behavior remains the execution path if capture is run.
|
|
- **Delegated start/completion UX behaviors**: N/A - no new capture start action, toast, DB notification, or run detail link is introduced.
|
|
- **Local surface-owned behavior that remains**: Existing diagnostic OperationRun references, if present, remain secondary/internal and authorized.
|
|
- **Queued DB-notification policy**: N/A - no new queued notification.
|
|
- **Terminal notification path**: Existing OperationRun lifecycle mechanism only.
|
|
- **Exception required?**: none.
|
|
|
|
## Provider Boundary / Platform Core Check *(mandatory)*
|
|
|
|
- **Shared provider/platform boundary touched?**: yes.
|
|
- **Boundary classification**: mixed. Coverage v2 evidence, identity, claim, redaction, and read-model semantics are platform-core; Security Defaults and Graph field names are provider-owned typed adapter details.
|
|
- **Seams affected**: source contract mapping, source class, resource type defaults, identity strategy, typed payload field mapping, compare/render interpretation, claim wording.
|
|
- **Neutral platform terms preserved or introduced**: workspace, managed environment, provider connection, resource type, evidence state, coverage level, identity state, claim state, compare result, render summary.
|
|
- **Provider-specific semantics retained and why**: `securityDefaults` and enabled-state semantics are necessary for this Microsoft Entra support slice. They must stay bounded to source metadata and typed helper code, not platform ownership truth.
|
|
- **Why this does not deepen provider coupling accidentally**: No provider-native tenant ID ownership, no Entra table family, no Entra dashboard, no provider framework, no customer claim activation, and no restore/certify support.
|
|
- **Follow-up path**: Later Entra certified compare pack, restore/apply, customer reporting, and additional Entra resource types require separate specs.
|
|
|
|
## UI / Surface Guardrail Impact *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|
|
|---|---|---|---|---|---|---|
|
|
| Existing Coverage v2 readiness / inspect surface data | yes, data-driven if summaries render | Native Filament existing surface | Coverage v2 evidence/readiness family | page/detail | no | No new route/action/navigation planned |
|
|
|
|
## Decision-First Surface Role *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|
|
|---|---|---|---|---|---|---|---|
|
|
| Existing Coverage v2 readiness / inspect surface | Tertiary Evidence / Diagnostics | Release/operator review of Security Defaults support | resource name, enabled/disabled/unknown summary, coverage/evidence/identity/claim state, blockers | raw/normalized payload, source metadata, unsupported fields, evidence hash, OperationRun link | Not primary; it supports internal evidence inspection and release review | Follows existing Coverage v2 internal review flow | Reduces raw-payload reading for Security Defaults |
|
|
|
|
## Audience-Aware Disclosure *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|
|
|---|---|---|---|---|---|---|---|
|
|
| Coverage v2 readiness / inspect | operator-MSP, support-platform | Security Defaults enabled state, evidence/identity/claim state, blocker summary | source contract, unsupported fields, source version, permission summary | raw payload, normalized JSON, permission context, source keys | Inspect | raw/support detail and OperationRun diagnostics | Security Defaults state appears once; no duplicate certified/readiness claim |
|
|
|
|
## UI/UX Surface Classification *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
| Coverage v2 readiness | List / Table / Report | Read-only registry/evidence inspection | Inspect Security Defaults evidence | Existing inspect affordance | existing behavior | not required | none | existing route | inspect disclosure | workspace + managed environment | Security Defaults | enabled state, coverage level, evidence state, identity state, claim state | none |
|
|
|
|
## Operator Surface Contract *(mandatory when operator-facing surfaces are changed)*
|
|
|
|
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|
|
|---|---|---|---|---|---|---|---|---|---|---|
|
|
| Coverage v2 readiness / inspect | internal operator / release reviewer | Verify Security Defaults can be interpreted safely | Technical Annex | Is Security Defaults content-backed and comparable/renderable? | enabled state, coverage/evidence/identity/claim state, blockers | raw payload, normalized JSON, source metadata, unsupported fields, OperationRun | coverage level, evidence state, identity state, claim state | read-only | Inspect | none |
|
|
|
|
## Proportionality Review *(mandatory when structural complexity is introduced)*
|
|
|
|
- **New source of truth?**: no. Security Defaults remains Coverage v2 evidence truth on existing resource/evidence rows.
|
|
- **New persisted entity/table/artifact?**: no planned.
|
|
- **New abstraction?**: no new broad abstraction planned; a focused source contract mapping, identity strategy entry, and typed helper extension are expected.
|
|
- **New enum/state/reason family?**: no planned. Existing `CaptureOutcome`, `CoverageLevel`, `EvidenceState`, `IdentityState`, `ClaimState`, `RestoreTier`, and compare labels should be reused. New reason codes may be stable strings only when they change blocker explanation.
|
|
- **New cross-domain UI framework/taxonomy?**: no.
|
|
- **Current operator problem**: Security Defaults is a core Entra setting required for later denominator truth, but current repo truth cannot capture or explain it.
|
|
- **Existing structure is insufficient because**: The existing Coverage v2 path is correct, but lacks the one source contract, identity strategy, and typed Security Defaults semantics needed to avoid raw-payload inspection and overclaim.
|
|
- **Narrowest correct implementation**: Extend only existing Coverage v2 source, capture, identity, Entra typed compare/render, read-model, redaction, and Claim Guard paths for `securityDefaults`.
|
|
- **Ownership cost**: Focused tests and maintenance of one source contract, one identity strategy, and one typed mapping.
|
|
- **Alternative intentionally rejected**: New Security Defaults engine/dashboard or broad Entra pack, because that would import routes, persistence, and product claims outside the current blocker.
|
|
- **Release truth**: Current-release internal support closure, not customer/certification/restore readiness.
|
|
|
|
## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)*
|
|
|
|
- **Test purpose / classification**: Unit for source contract, normalizer, comparator, render summary, Claim Guard, redaction; Feature for capture/evidence, RBAC/scope, no certification/restore/customer claim, no `tenant_id`, no mini-platform; Browser only if rendered output changes.
|
|
- **Validation lane(s)**: focused Sail/Pest fast-feedback and confidence lanes; browser lane only when rendered output changes; PostgreSQL lane only if implementation touches JSONB/schema/index behavior, which is not planned.
|
|
- **Why this classification and these lanes are sufficient**: The behavior is service-level and existing-surface rendering over existing persistence. Unit/feature tests prove business truth; browser proof proves rendered Product Surface safety if needed.
|
|
- **New or expanded test families**: focused Spec 424 TenantConfiguration tests; no broad heavy-governance family.
|
|
- **Fixture / helper cost impact**: Minimal workspace, managed environment, provider connection, OperationRun, and fake Security Defaults payload fixtures. No live Graph, TCM, Microsoft docs, or network calls.
|
|
- **Heavy-family visibility / justification**: none planned.
|
|
- **Special surface test profile**: Technical Annex / existing Coverage v2 surface if rendered output changes.
|
|
- **Standard-native relief or required special coverage**: Existing internal surface only; focused browser proof instead of full page audit unless UI files/routes/navigation change.
|
|
- **Reviewer handoff**: Confirm lane fit, fake payload minimality, no live provider calls, no broad Entra scope, and exact proof commands.
|
|
- **Budget / baseline / trend impact**: none expected.
|
|
- **Escalation needed**: none if scope stays limited to Security Defaults support closure.
|
|
- **Active feature PR close-out entry**: Guardrail / Exception / Smoke Coverage.
|
|
- **Planned validation commands**:
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=Spec424`
|
|
- `cd apps/platform && ./vendor/bin/sail artisan test --filter=ClaimGuard`
|
|
- `cd apps/platform && ./vendor/bin/sail bin pint --dirty --format agent`
|
|
- `git diff --check`
|
|
- focused browser test command if rendered output changes
|
|
|
|
## User Scenarios & Testing *(mandatory)*
|
|
|
|
### User Story 1 - Capture Real Security Defaults Evidence (Priority: P1)
|
|
|
|
As an internal operator preparing an Entra compare baseline, I need Security Defaults captured through the existing Coverage v2 source-contract path so later comparison is based on real content, not a registry placeholder.
|
|
|
|
**Independent Test**: Given a valid source contract and fake provider response for Security Defaults, capture persists raw and normalized payloads, payload hash, provider scope, OperationRun link, and content-backed evidence. Given no valid contract, capture produces a blocked outcome and no fake evidence.
|
|
|
|
**Acceptance Scenarios**:
|
|
|
|
1. Given no approved source contract mapping exists, when capture requests `securityDefaults`, then the result is `capture_blocked_missing_contract` or the repo-equivalent blocked outcome with a stable reason code and no evidence row.
|
|
2. Given an approved v1 source contract and successful fake provider response, when capture runs through the existing tenant-configuration capture operation, then one Security Defaults evidence row is persisted as content-backed.
|
|
3. Given provider permission is missing, when capture runs, then the result is blocked or failed safely with sanitized context and no fake content-backed evidence.
|
|
|
|
### User Story 2 - Compare Enabled-State Changes Deterministically (Priority: P1)
|
|
|
|
As an operator reviewing two captured states, I need Security Defaults enabled-state changes to be classified consistently so a material security posture change is never hidden as metadata noise.
|
|
|
|
**Independent Test**: Compare output detects false-to-true, true-to-false, null-to-known, added, removed, unchanged, volatile-only, redacted, and unsupported-field cases with stable ordering and critical importance for enabled-state changes.
|
|
|
|
### User Story 3 - Render an Operator-Safe Security Defaults Summary (Priority: P1)
|
|
|
|
As an operator, I need a concise Security Defaults summary that answers whether it is enabled, content-backed, comparable, renderable, and safe for later certification inclusion without exposing raw Graph payloads.
|
|
|
|
**Independent Test**: Render output shows enabled/disabled/unknown, evidence state, identity state, claim state, last captured time, and blockers while hiding raw payload, normalized JSON, permission context, tokens, secrets, provider response bodies, and source keys by default.
|
|
|
|
### User Story 4 - Prevent Overclaim, Restore, and Customer Output (Priority: P1)
|
|
|
|
As a release reviewer, I need Claim Guard, RBAC, Product Surface, and no-mini-platform proof so Security Defaults support cannot be mistaken for Entra certification, restore readiness, full coverage, or customer-ready proof.
|
|
|
|
**Independent Test**: Claim Guard allows only scoped internal/operator content-backed/comparable/renderable claims and blocks certified, restore-ready, customer-ready, full Entra, 100 percent, broad M365, report/review-pack, and restore/apply claims. Feature tests prove no customer output, no restore action, no new route/dashboard, and no `tenant_id`.
|
|
|
|
## Functional Requirements *(mandatory)*
|
|
|
|
- **FR-424-001**: The implementation MUST use existing Coverage v2 source contract, capture, resource/evidence, identity, redaction, read-model, and Claim Guard boundaries.
|
|
- **FR-424-002**: `securityDefaults` MUST remain the only resource type in scope.
|
|
- **FR-424-003**: The resource type registry MUST either keep Security Defaults safely blocked or promote it only when source contract, capture, identity, normalize, compare, render, redaction, and Claim Guard tests pass.
|
|
- **FR-424-004**: Any source contract MUST be explicit in the repo graph contract registry and routed through `GraphClientInterface` via existing provider gateway/capture paths.
|
|
- **FR-424-005**: Missing contract, unsupported source, missing permission, beta-only source, or failed capture MUST not create fake raw payloads, normalized payloads, content-backed evidence, comparable support, or renderable support.
|
|
- **FR-424-006**: Captured evidence MUST persist raw payload, normalized payload, payload hash, source metadata, redacted permission context, `operation_run_id`, `workspace_id`, `managed_environment_id`, and same-scope `provider_connection_id` through existing tables.
|
|
- **FR-424-007**: Provider connection scope MUST be validated against the same workspace and managed environment as the resource/evidence and OperationRun.
|
|
- **FR-424-008**: Security Defaults identity MUST use `CanonicalIdentityResolver` and MUST never treat display name alone as stable identity.
|
|
- **FR-424-009**: Typed normalization MUST produce deterministic Security Defaults fields including resource type, enabled state, source identity, source class, source version/schema when known, capture timestamp context, and unsupported-field diagnostics.
|
|
- **FR-424-010**: Volatile metadata such as OData context/etag and timestamp/request/correlation fields MUST be ignored or diagnostics-only for compare purposes.
|
|
- **FR-424-011**: Compare output MUST classify added, removed, changed, unchanged, ignored volatile, unsupported field, and redacted cases.
|
|
- **FR-424-012**: Enabled-state changes MUST be classified as critical compare changes.
|
|
- **FR-424-013**: Render output MUST be operator-safe and must not require raw payload display to answer enabled/disabled/unknown, evidence state, identity state, claim state, last captured, and blocker questions.
|
|
- **FR-424-014**: Claim Guard MUST allow only scoped internal/operator statements for Security Defaults content-backed/comparable/renderable support.
|
|
- **FR-424-015**: Claim Guard MUST block Security Defaults certified, restore-ready, customer-ready, full Entra, 100 percent Entra, M365 certified, report/review-pack, legal/regulatory, and restore/apply claims.
|
|
- **FR-424-016**: No restore/apply action, restore claim, customer output, report, Review Pack inclusion, export, dashboard, or new route/navigation may be introduced.
|
|
- **FR-424-017**: No `tenant_id` may be introduced as Coverage v2 ownership truth, compatibility alias, dual-write target, fallback reader, or parallel scope key.
|
|
- **FR-424-018**: Runtime render/compare/readiness paths MUST perform no Graph, TCM, HTTP, Microsoft docs, or provider calls.
|
|
- **FR-424-019**: Existing Coverage v2 rendered output MAY show Security Defaults summary on the internal/operator surface; any rendered change requires focused browser proof and Human Product Sanity.
|
|
- **FR-424-020**: Any supported-scope entry or resolver behavior added for Security Defaults MUST be internal/operator-only and MUST NOT use forbidden scope names such as `entra_certified`, `entra_full_coverage`, `entra_restore_ready`, or `m365_certified`.
|
|
- **FR-424-021**: Implementation close-out MUST record source contract result, evidence/capture matrix, identity strategy, supported-scope posture, normalizer/compare/render matrices, Claim Guard proof, redaction proof, no restore/certification/customer proof, no `tenant_id`, no mini-platform, Product Surface result, tests/browser/no-browser, deployment impact, and deferred work.
|
|
|
|
## Non-Functional Requirements
|
|
|
|
- **NFR-424-001**: Tests and runtime code MUST use fake provider payloads and must not require live Graph, TCM, Microsoft documentation, or network access.
|
|
- **NFR-424-002**: The implementation MUST preserve existing workspace, managed-environment, provider-connection, RBAC, OperationRun, and redaction contracts.
|
|
- **NFR-424-003**: Any new Graph contract or registry default MUST be covered by unit/feature tests so support cannot silently drift.
|
|
- **NFR-424-004**: The implementation MUST remain small enough for one bounded implementation loop and must stop if a singleton capture framework, broad Entra platform, migration, or new UI surface becomes necessary.
|
|
|
|
## Data / Truth Source Requirements
|
|
|
|
- **Execution truth**: Existing `OperationRun` for tenant-configuration capture.
|
|
- **Artifact/evidence truth**: Existing `TenantConfigurationResource` and `TenantConfigurationResourceEvidence` rows.
|
|
- **Source truth**: Microsoft Graph through explicit repo graph contract and `GraphClientInterface`, or safe blocked state if no contract is approved.
|
|
- **Claim truth**: Existing `ClaimGuard` output, not UI wording alone.
|
|
- **Display truth**: Derived render summary from redacted normalized evidence, not raw payload display.
|
|
|
|
## Out Of Scope
|
|
|
|
- Entra certification or certified denominator activation.
|
|
- Restore/apply, preview restore, assisted restore, or restore readiness.
|
|
- Customer-facing Entra claims, reports, Review Pack output, PDF/export/download output.
|
|
- Full Entra, full M365, Application, Service Principal, Role Definition, Administrative Unit, Authentication Methods, Identity Protection, Authorization Policy, Cross-Tenant Access, Access Review, or PIM support.
|
|
- New Entra dashboard, route, navigation entry, mini-platform, table family, persisted compare table, or broad source framework.
|
|
- Live Microsoft docs fetch, direct HTTP client, Graph SDK bypass, endpoint guessing from resource type name.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- **AC-424-001**: Security Defaults has either a valid source contract and content-backed evidence path or a safe blocked missing-contract/unsupported state with no fake evidence.
|
|
- **AC-424-002**: Captured Security Defaults evidence stores raw payload, normalized payload, payload hash, source metadata, redacted permission context, OperationRun link, and same-scope ownership fields through existing tables.
|
|
- **AC-424-003**: Canonical identity resolution is used and unsafe identity states block or limit claims.
|
|
- **AC-424-004**: Deterministic compare detects enabled-state changes as critical and ignores volatile-only changes.
|
|
- **AC-424-005**: Operator-safe render summary answers enabled/disabled/unknown, content-backed, comparable, renderable, blocker, and last captured questions without raw payload display.
|
|
- **AC-424-006**: Claim Guard blocks certification, restore, customer-ready, report/review-pack, full Entra, 100 percent, broad M365, and legal/regulatory claims.
|
|
- **AC-424-007**: RBAC and scope tests prove 404 for non-member/wrong scope, 403 for established member without capability, readonly cannot start capture, and provider connections are same-scope.
|
|
- **AC-424-008**: No `tenant_id`, new route/navigation/dashboard, restore action, customer output, or Security Defaults mini-platform is introduced.
|
|
- **AC-424-009**: Browser proof and Human Product Sanity are recorded if rendered output changes; otherwise exact no-rendered-change proof is recorded.
|
|
|
|
## Success Criteria
|
|
|
|
- Security Defaults is eligible for later certified Entra denominator work because it is content-backed, comparable, renderable, and claim-limited internally.
|
|
- Later Entra certification work can depend on real Security Defaults evidence instead of a registry-only placeholder.
|
|
- The Coverage v2 path remains conservative: blocked means blocked, and no customer/restore/certification claims are activated.
|
|
|
|
## Risks
|
|
|
|
| Risk | Severity | Mitigation |
|
|
|---|---|---|
|
|
| Source contract cannot capture singleton payload through existing list path | High | Prove through focused tests; add only bounded singleton handling inside existing source/capture path or leave blocked |
|
|
| Security Defaults support is mistaken for certification | High | Claim Guard, wording restrictions, Product Surface proof, implementation report |
|
|
| Beta-only or unsupported source is promoted | High | Source-class tests, beta guard, certified-claim block |
|
|
| Raw payload or permission context leaks | High | Redaction tests, render summary tests, browser proof if rendered |
|
|
| Broad Entra scope creeps in | Medium | Explicit non-goals, stop conditions, tasks limited to `securityDefaults` |
|
|
|
|
## Assumptions
|
|
|
|
- Existing Coverage v2 tables can represent Security Defaults evidence without migration.
|
|
- `ResourceTypeRegistry::syncDefaults()` is expected to be the canonical runtime default-sync path; implementation preflight found the existing fresh-install migration seed also lists `securityDefaults`, so this spec permits only that one-row seed alignment after real source support is proven. Any other migration-seed edit or new migration remains out of scope.
|
|
- Existing capture OperationRun type is sufficient for remote/provider work.
|
|
- Existing Entra comparable/renderable helper family can be extended or mirrored without a new registry/framework.
|
|
- Current repo pre-production posture allows clean replacement of the registry-only Security Defaults row when support is proven.
|
|
|
|
## Open Questions
|
|
|
|
None block preparation. Implementation preflight must verify whether the repo-approved source contract can capture the singleton Security Defaults payload safely. If not, the implementation must keep Security Defaults blocked and record the blocker instead of widening scope.
|
|
|
|
## Follow-Up Spec Candidates
|
|
|
|
- Entra Certified Core Compare Pack including Conditional Access and Security Defaults.
|
|
- Customer-safe Entra reporting / Review Pack claim guard.
|
|
- Entra restore/apply safety exploration.
|
|
- Additional Entra resource packs for Applications, Service Principals, Role Definitions, Administrative Units, authentication methods, and related identity governance domains.
|