TenantAtlas/specs/255-enforce-finding-creation-invariants/spec.md
ahmido ab9c36f21e
Some checks failed
Main Confidence / confidence (push) Failing after 59s
Automatische PR: platform-dev → dev (#299)
Automatisch erstellt: Merge `platform-dev` into `dev` (via MCP)

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #299
2026-04-29 12:37:48 +00:00

30 KiB

Feature Specification: Enforce Creation-Time Finding Invariants

Feature Branch: 255-enforce-finding-creation-invariants
Created: 2026-04-29
Status: Draft
Input: User description: "Prepare only the spec artifacts for Enforce Creation-Time Finding Invariants on the existing 255 branch as the next bounded findings data-integrity slice after Specs 253 and 254."

Spec Candidate Check (mandatory - SPEC-GATE-001)

  • Problem: Findings that reach operators through active generators already tend to look lifecycle-ready, but that truth is still implied and distributed. If a new or changed generator path omits status, seen timestamps, seen count, or due/SLA initialization, operators can receive findings that look real before they are workflow-ready.
  • Today's failure: TenantPilot would have to rely on scattered implicit behavior or future repair logic to make a new or recurring finding usable. That weakens trust in due state, recurrence history, and reopen behavior right at the moment an operator is asked to act.
  • User-visible improvement: Newly created or reopened findings arrive already ready for existing workflow use, with stable identity and lifecycle metadata that operators can trust immediately.
  • Smallest enterprise-capable version: Make creation-time and recurrence-time finding invariants explicit for the active generator families and their shared reopen semantics, backed by focused regression proof, while reusing existing finding fields and workflow states only.
  • Explicit non-goals: No backfill runtime surfaces, no acknowledged cleanup, no new customer-facing workflow, no broader findings lifecycle redesign, no new persistence, no new states, no external integration, no owner/assignee mandate, and no schema rollout except a possible future narrow follow-up.
  • Permanent complexity imported: Low and bounded. The feature should add only explicit invariant coverage and possibly a narrow shared write-time guard if planning proves it necessary; no new table, state family, framework, or operator surface is justified.
  • Why now: Specs 253 and 254 remove adjacent repair and compatibility debt. The next bounded unspecced findings candidate is to lock in the post-cleanup target state so active generators cannot drift back into repair-tool dependency.
  • Why not local: Repo truth spans baseline compare, Entra admin roles, permission posture, shared reopen behavior, SLA/due initialization, and recurrence semantics. A local fix in one generator would leave the others as implied behavior and keep the invariant unowned.
  • Approval class: Core Enterprise
  • Red flags triggered: Multiple micro-specs for one domain. Defense: this is the final bounded data-integrity hardening slice after surface removal and acknowledged cleanup, and it explicitly avoids bundling broader lifecycle redesign or new infrastructure.
  • Score: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 2 | Produktnaehe: 1 | Wiederverwendung: 2 | Gesamt: 11/12
  • Decision: approve

Selection Rationale

  • The source candidate is the active P1 entry Enforce Creation-Time Finding Invariants in docs/product/spec-candidates.md.
  • This slice sits in the Findings Workflow / Data Integrity sequence and follows Spec 253 (Remove Findings Lifecycle Backfill Runtime Surfaces) and Spec 254 (Remove Legacy Acknowledged Finding Status Compatibility).
  • It is the next bounded unspecced candidate in repo order. Customer Review Workspace, Decision-Based Governance Inbox, Commercial Entitlements and Billing-State Maturity, Platform Localization, Remove Findings Lifecycle Backfill Runtime Surfaces, and Remove Legacy Acknowledged Finding Status Compatibility already have specs.
  • External Support Desk / PSA Handoff remains blocked because the repo still does not name one concrete external desk or PSA target.
  • Cross-Tenant Compare and Promotion v1 already has Spec 043 and is a refresh candidate, not the next unspecced preparation target.
  • The smallest viable slice is to prove that active finding generators and reopen/recurrence paths always create or refresh findings in a lifecycle-ready state at write time, without reintroducing repair tooling, redesigning the lifecycle, adding new persistence, adding new workflow states, or widening into external workflow work.

Spec Scope Fields (mandatory)

  • Scope: tenant
  • Primary Routes:
    • No new or changed direct route is the product target.
    • Existing tenant findings surfaces are downstream regression consumers only: /admin/t/{tenant}/findings and /admin/t/{tenant}/findings/{record}.
    • In-scope behavior is reached through existing tenant-scoped finding generation paths, including baseline compare completion, Entra admin role finding generation, and permission posture finding generation.
  • Data Ownership:
    • Tenant-owned Finding records remain the canonical truth and keep required workspace_id plus tenant_id anchors.
    • Existing OperationRun and StoredReport references stay contextual only where the current generators already use them; this feature introduces no new persisted entity, mirror table, or compatibility artifact.
    • The scope is limited to write-time creation and refresh behavior for existing finding truth.
  • RBAC:
    • Tenant membership remains the isolation boundary for the downstream findings surfaces that consume these records.
    • Existing user-triggered paths that lead to in-scope finding creation remain capability-first; non-members stay 404 and members lacking the current capability stay 403.
    • Background or system-triggered generation must preserve tenant/workspace isolation and must not create a bypass that can write findings outside the current tenant scope.

Cross-Cutting / Shared Pattern Reuse (mandatory when the feature touches notifications, status messaging, action links, header actions, dashboard signals/cards, alerts, navigation entry points, evidence/report viewers, or any other existing shared operator interaction family; otherwise write N/A - no shared interaction family touched)

  • Cross-cutting feature?: no
  • Interaction class(es): N/A - no shared operator interaction family is added or changed
  • Systems touched: N/A - operator-facing shared interaction patterns stay unchanged
  • Existing pattern(s) to extend: none
  • Shared contract / presenter / builder / renderer to reuse: none
  • Why the existing shared path is sufficient or insufficient: This slice hardens tenant-owned finding writes and shared lifecycle semantics, not notifications, action surfaces, or dashboard presentation.
  • Allowed deviation and why: none
  • Consistency impact: downstream findings and review surfaces continue consuming the same finding truth without any new UI branch
  • Review focus: reviewers should verify that the feature stays in write-time lifecycle hardening and does not smuggle in new operator interaction patterns
  • Touches OperationRun start/completion/link UX?: no
  • Shared OperationRun UX contract/layer reused: N/A
  • Delegated start/completion UX behaviors: N/A
  • Local surface-owned behavior that remains: existing baseline compare and other current generation flows keep their current launch, completion, and link UX; this slice only hardens the finding writes they already produce
  • Queued DB-notification policy: N/A
  • Terminal notification path: N/A
  • Exception required?: none

Provider Boundary / Platform Core Check (mandatory when the feature changes shared provider/platform seams, identity scope, governed-subject taxonomy, compare strategy selection, provider connection descriptors, or operator vocabulary that may leak provider-specific semantics into platform-core truth; otherwise write N/A - no shared provider/platform boundary touched)

  • Shared provider/platform boundary touched?: no
  • Boundary classification: N/A
  • Seams affected: N/A
  • Neutral platform terms preserved or introduced: N/A
  • Provider-specific semantics retained and why: N/A
  • Why this does not deepen provider coupling accidentally: The slice hardens existing tenant-owned finding lifecycle truth across already-active generators without introducing a new shared provider seam, taxonomy, or vocabulary.
  • Follow-up path: none

UI / Surface Guardrail Impact (mandatory when operator-facing surfaces are changed; otherwise write N/A)

N/A - no operator-facing surface change. Existing findings, review, and summary surfaces are regression consumers of better write-time truth, not redesign targets in this feature.

Proportionality Review (mandatory when structural complexity is introduced)

  • New source of truth?: no
  • New persisted entity/table/artifact?: no
  • New abstraction?: no
  • New enum/state/reason family?: no
  • New cross-domain UI framework/taxonomy?: no
  • Current operator problem: Operators should not receive a newly created or reopened finding that still depends on an implicit later repair step before due state, seen history, or canonical workflow use is trustworthy.
  • Existing structure is insufficient because: the write-time invariant exists only as distributed repo behavior today. It is partially proven in separate tests, but not yet owned as one explicit product hardening slice across the active generator families and their recurrence semantics.
  • Narrowest correct implementation: make the invariant explicit across the verified active generator families and shared reopen/recurrence behavior, using the existing finding fields, existing workflow states, existing SLA policy, and focused regression proof only.
  • Ownership cost: a small amount of enduring regression coverage and possibly a narrow shared write-time guard if planning proves it necessary. No new table, state family, or general framework is justified.
  • Alternative intentionally rejected: reintroducing lifecycle backfill or repair tooling, adding a new invariant framework or persistence layer, or widening into a broader findings lifecycle redesign.
  • Release truth: current-release truth

Compatibility posture

This feature assumes a pre-production environment.

Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.

Canonical replacement is preferred over preservation.

Testing / Lane / Runtime Impact (mandatory for runtime behavior changes)

  • Test purpose / classification: Feature
  • Validation lane(s): fast-feedback, confidence
  • Why this classification and these lanes are sufficient: the behavioral proof stays centered on the three focused writer suites around baseline compare, Entra admin roles, and permission posture, with only bounded adjacent regression in shared recurrence/workflow-service and downstream consumer/auth continuity tests because FR-255-005, FR-255-006, FR-255-009, and FR-255-011 cross the writer boundaries.
  • New or expanded test families: none by default; reuse and tighten the three focused writer suites, plus bounded regression in apps/platform/tests/Feature/Findings/FindingRecurrenceTest.php, apps/platform/tests/Feature/Findings/FindingAutomationWorkflowTest.php, apps/platform/tests/Feature/Findings/FindingWorkflowServiceTest.php, apps/platform/tests/Feature/Findings/MyWorkInboxTest.php, apps/platform/tests/Feature/Findings/FindingsIntakeQueueTest.php, apps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php, and apps/platform/tests/Feature/EntraAdminRoles/AdminRolesSummaryWidgetTest.php only where they prove shared recurrence, consumer honesty, or unchanged trigger authorization
  • Fixture / helper cost impact: low and near-neutral. The default path should reuse existing tenant, finding, and operation helpers instead of adding a broader harness.
  • Heavy-family visibility / justification: none. No new heavy-governance or browser family is justified for this slice.
  • Special surface test profile: N/A
  • Standard-native relief or required special coverage: ordinary feature coverage is sufficient because this slice hardens domain truth behind existing workflows rather than adding a new UI surface
  • Reviewer handoff: reviewers must confirm that the final proof covers new finding creation, repeated observation, resolved-to-reopened transitions, unchanged 404 versus 403 semantics on the existing trigger surfaces, and preserved current_operation_run_id meaning without expanding into unrelated workflow or UI coverage
  • Budget / baseline / trend impact: none expected beyond ordinary focused feature-test upkeep
  • Escalation needed: none
  • Active feature PR close-out entry: Guardrail
  • Planned validation commands:
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Baselines/BaselineCompareFindingsTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/EntraAdminRoles/EntraAdminRolesFindingGeneratorTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/PermissionPosture/PermissionPostureFindingGeneratorTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/FindingRecurrenceTest.php tests/Feature/Findings/FindingAutomationWorkflowTest.php tests/Feature/Findings/FindingWorkflowServiceTest.php
    • export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/Findings/MyWorkInboxTest.php tests/Feature/Findings/FindingsIntakeQueueTest.php tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php tests/Feature/EntraAdminRoles/AdminRolesSummaryWidgetTest.php

RBAC / Isolation Considerations

  • Tenant-owned findings remain scoped by workspace_id and tenant_id. The feature must not create or preserve tenantless finding truth.
  • Existing user-triggered operations that can lead to the in-scope finding writes keep current capability-first authorization. This slice does not add a new capability or role alias.
  • Downstream findings and review surfaces keep current deny-as-not-found versus forbidden behavior: non-members remain 404, in-scope members missing the existing capability remain 403 on triggering actions.
  • Explicit 404 versus 403 continuity proof stays bounded to apps/platform/tests/Feature/Rbac/BaselineCompareMatrixAuthorizationTest.php and apps/platform/tests/Feature/EntraAdminRoles/AdminRolesSummaryWidgetTest.php, because permission posture finding generation is background-triggered rather than launched from a separate tenant UI action.
  • System-initiated reopen or refresh behavior stays inside the current tenant/workspace context and must not widen read or write visibility across tenants.

Auditability

  • Existing workflow-driven reopen semantics remain authoritative for system reopen behavior. The feature must preserve current audit and workflow meaning instead of introducing a silent side path.
  • Existing current_operation_run_id correlations stay in place where the current generators already populate them; this slice does not add a second run-correlation path or new audit artifact.
  • The hardening must not allow partially initialized findings to look settled or complete on downstream operator surfaces. The audit trail should continue to explain system-created and system-reopened findings through the existing lifecycle paths.

User Scenarios & Testing (mandatory)

User Story 1 - See Ready Findings Immediately (Priority: P1)

As a tenant operator, I want a newly detected finding to arrive already ready for the existing findings workflow so I can trust the status, due state, and seen history the first time it appears.

Why this priority: This is the core product-truth outcome. If new findings still depend on implied repair logic, the feature has failed.

Independent Test: Can be fully tested by triggering one new finding in each in-scope generator family and verifying that the first persisted record is already lifecycle-ready before any downstream findings page or review surface consumes it.

Acceptance Scenarios:

  1. Given a baseline compare run detects new drift for a tenant, When the finding is first written, Then it already carries the canonical open status, first seen and last seen timestamps, seen count, and the due or SLA data required by the existing workflow.
  2. Given an Entra admin roles or permission posture run detects a new issue, When the tenant findings register later displays that record, Then no backfill, repair action, or second pass is required to make the finding usable in the existing workflow.

User Story 2 - Reopen the Same Finding When the Risk Returns (Priority: P1)

As a tenant operator, I want a resolved issue that reappears to reopen the same finding with fresh lifecycle truth so I can continue work with the existing history instead of receiving a duplicate or stale record.

Why this priority: Reopen behavior is the critical recurrence path that keeps findings trustworthy after the cleanup sequence in Specs 253 and 254.

Independent Test: Can be fully tested by resolving an in-scope finding, observing the same issue again, and verifying that the existing finding reopens with refreshed lifecycle fields.

Acceptance Scenarios:

  1. Given a previously resolved baseline drift finding reappears, When the same drift is observed again, Then the existing finding reopens, resolved markers clear as needed, and the lifecycle fields required for current workflow use are refreshed at write time.
  2. Given a previously resolved Entra admin roles or permission posture finding reappears, When the generator sees the same active issue again, Then the system reopens the same finding identity and refreshes the due or SLA truth according to the current severity policy already in use.

User Story 3 - Keep One Canonical Finding Identity Through Repeated Detection (Priority: P2)

As a tenant operator, I want repeated detection of the same active issue to strengthen the same finding record instead of creating uncontrolled duplicates or inflating seen counts incorrectly.

Why this priority: Stable recurrence semantics protect operator trust in counts, history, and due attention without widening the feature into broader lifecycle redesign.

Independent Test: Can be fully tested by retrying or repeating the same observation across the in-scope families and verifying one canonical finding identity with bounded seen-count updates.

Acceptance Scenarios:

  1. Given the same canonical issue is retried under the same observation identity, When the generator processes it again, Then the system does not create a duplicate finding and does not double-count the same observation.
  2. Given the same canonical issue is observed again under a later valid observation, When the generator refreshes the existing finding, Then the same finding identity remains in place and the seen history advances according to that family's existing recurrence semantics.

Edge Cases

  • A retried baseline compare job using the same run identity must not increment times_seen twice for the same observation.
  • An existing finding encountered on a normal active path may still be missing first_seen_at, last_seen_at, or times_seen; the in-scope write path must repair those fields inline instead of depending on a separate repair surface.
  • A resolved finding should reopen only when the new observation is later than the prior resolution boundary; out-of-order or stale observations must not incorrectly reopen it.
  • If current SLA policy derives a due date from severity, the reopened or newly created record must be ready for that downstream truth immediately; the feature must not defer due-state initialization to a later process.
  • The feature must preserve one canonical finding identity even when evidence payloads or current hashes change between observations.

Requirements (mandatory)

Constitution alignment (required): This feature changes tenant-owned finding write behavior but does not add Microsoft Graph calls, a new user-facing mutation surface, or a new long-running workflow. It hardens existing write-time semantics in current generator paths, preserves tenant isolation, preserves existing audit meaning plus current_operation_run_id correlation on the in-scope write paths, and requires focused regression proof.

Constitution alignment (PROP-001 / ABSTR-001 / PERSIST-001 / STATE-001 / BLOAT-001): The slice must not introduce new persistence, new abstraction, new state family, or new semantic layer. If planning proposes a shared invariant helper, it must prove why the existing distributed write paths cannot safely stay explicit without creating a new unowned drift point.

Constitution alignment (XCUT-001): No new cross-cutting operator interaction family is allowed in this slice. Existing findings, review, and summary surfaces remain unchanged consumers of better write-time truth.

Constitution alignment (TEST-GOV-001): Proof stays in the narrow focused feature tests already closest to the active generator families and their recurrence behavior. The feature must not create a new heavy family or browser dependency.

Constitution alignment (OPS-UX / OPS-UX-START-001): Existing baseline compare and other current generation flows may continue using their current OperationRun semantics where already present, but this feature does not add or change operation start UX, queued notification policy, or deep-link behavior.

Constitution alignment (RBAC-UX): Existing triggering authorization stays capability-first and unchanged. The feature must not add a hidden bypass or new capability branch to create or reopen findings.

Constitution alignment (OPSURF-001 / DECIDE-AUD-001): Existing operator surfaces must never depend on partially initialized finding truth. The hardening exists so downstream decision surfaces continue to show calm, honest workflow data without false readiness.

Functional Requirements

  • FR-255-001: The system MUST ensure each in-scope active finding generator family writes a newly created finding in a lifecycle-ready state within the same write path that first persists the record.
  • FR-255-002: The in-scope active generator families for this feature are baseline compare drift, Entra admin roles, and permission posture. The invariant MUST be explicit across all three families, not only one local path.
  • FR-255-003: A newly created in-scope finding MUST carry the canonical initial workflow status plus the lifecycle fields needed by existing downstream workflow surfaces, including first seen and last seen timestamps, a valid seen count, and existing SLA or due-date truth when the current severity policy already requires them.
  • FR-255-004: Repeated observation of the same active condition MUST reuse one canonical finding identity through the existing recurrence key or fingerprint semantics and MUST refresh the existing record instead of creating uncontrolled canonical duplicates.
  • FR-255-005: A retry or repeated processing of the same observation identity MUST NOT double-count the same observation. Each in-scope generator family may keep its current observation semantics, but the feature MUST make those semantics explicit and regression-protected.
  • FR-255-006: When a previously resolved in-scope finding reappears, the system MUST reopen the existing finding through the current workflow path and MUST clear or refresh the lifecycle data required for immediate downstream workflow use.
  • FR-255-007: If an in-scope active path encounters an existing finding with missing lifecycle fields covered by this slice, the normal write path MUST repair those fields inline instead of depending on backfill jobs, tenant repair actions, CLI repair commands, or deploy-time hooks.
  • FR-255-008: The feature MUST preserve current tenant/workspace isolation by keeping every in-scope finding write anchored to the current tenant and workspace and by not widening visibility or write scope across tenants.
  • FR-255-009: The feature MUST preserve capability-first RBAC and existing 404 versus 403 semantics on the current user-triggered entry points that lead to in-scope finding creation or refresh, specifically the baseline compare matrix and admin-roles scan surfaces.
  • FR-255-010: The feature MUST preserve existing finding workflow states, downstream review surfaces, and operator affordances. It MUST NOT add new workflow states, reintroduce repair tooling, re-open acknowledged-status cleanup, require owner or assignee fields, or add external support or PSA workflow scope.
  • FR-255-011: The feature MUST keep existing audit meaning and current_operation_run_id correlation intact where the current generators already attach reopened or refreshed findings to system workflow paths.
  • FR-255-012: Regression proof MUST make the invariant explicit across new creation, repeated observation, and resolved-to-reopened behavior for the in-scope generator families.
  • FR-255-013: Any database constraint or migration-based invariant enforcement beyond the existing application write paths is out of scope for this feature and MAY only be considered as a later narrow follow-up if planning proves it is compatibility-safe and materially smaller than a broader redesign.

Key Entities (include if feature involves data)

  • Lifecycle-ready finding: A tenant-owned finding record that is immediately usable in the existing workflow because it already has canonical lifecycle status, seen history, recurrence identity, and due/SLA truth where current policy requires it.
  • Finding generator family: One of the active repo-owned write paths that creates or refreshes findings today: baseline compare drift, Entra admin roles, or permission posture.
  • Recurrence identity: The existing recurrence key or fingerprint semantics that decide whether repeated observation refreshes one finding or incorrectly creates a new one.

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001: During regression validation, 100% of newly created in-scope findings arrive with the lifecycle data needed by the existing downstream workflow in the same observation cycle that first persists them.
  • SC-002: During regression validation, 0 in-scope active finding paths require a separate repair, backfill, or deploy-time step before newly created or reopened findings are safe to show on existing workflow surfaces.
  • SC-003: During regression validation, repeated observation of the same in-scope issue reuses one canonical finding identity instead of creating uncontrolled duplicates across each in-scope generator family.
  • SC-004: During regression validation, previously resolved in-scope findings reopen through the existing workflow path with refreshed lifecycle truth across each in-scope generator family.

Dependencies

  • The baseline compare finding creation and recurrence path in apps/platform/app/Jobs/CompareBaselineToTenantJob.php
  • The Entra admin roles finding creation and reopen path in apps/platform/app/Services/EntraAdminRoles/EntraAdminRolesFindingGenerator.php
  • The permission posture finding creation and reopen path in apps/platform/app/Services/PermissionPosture/PermissionPostureFindingGenerator.php
  • Existing shared finding lifecycle behavior such as reopen semantics and SLA/due calculation already used by those paths
  • Existing focused regression proof in:
    • apps/platform/tests/Feature/Baselines/BaselineCompareFindingsTest.php
    • apps/platform/tests/Feature/EntraAdminRoles/EntraAdminRolesFindingGeneratorTest.php
    • apps/platform/tests/Feature/PermissionPosture/PermissionPostureFindingGeneratorTest.php

Assumptions

  • Spec 253 removes the visible lifecycle backfill runtime surfaces and Spec 254 removes acknowledged compatibility first, so this slice can focus only on the post-cleanup target state.
  • The three verified active generator families above are the full bounded scope for this feature unless planning finds another currently active finding writer that is equally first-class and already shipping.
  • Lifecycle-ready does not make owner, assignee, or additional governance fields mandatory. It only covers the existing lifecycle truth needed for current workflow readiness.
  • The product remains pre-production, so historical data migration, compatibility shims, and retained repair tooling are not justified.
  • Downstream findings, review, and summary surfaces should continue working without design changes if write-time truth is hardened correctly.

Risks

  • Another active finding writer may exist outside the three verified families and remain unsafely implicit if planning does not confirm the full set before implementation.
  • Over-eager implementation could introduce a generic invariant framework or broaden into lifecycle redesign, which would violate the intended slice boundary.
  • Different generator families already count repeated observation differently; forcing one artificial rule instead of preserving each family's valid observation semantics could create regressions while trying to harden the invariant.

Out of Scope

  • Reintroducing findings lifecycle backfill runtime surfaces, repair commands, deploy hooks, or tenant repair actions
  • Removing acknowledged compatibility or changing broader findings workflow vocabulary, which is already covered by Spec 254
  • New customer-facing workflow surfaces, review inbox redesign, customer review workspace work, or localization work
  • New persistence, new workflow states, new owner/assignee requirements, or broader findings lifecycle redesign
  • External Support Desk / PSA Handoff work
  • Cross-Tenant Compare and Promotion refresh work already tracked under Spec 043
  • Schema changes, migrations, or database constraints except as an explicit later follow-up candidate

Follow-up Candidates

  1. A very narrow database-level invariant guard may be considered later only if planning proves it can enforce one of these fields safely without reopening compatibility or widening the feature.
  2. External Support Desk / PSA Handoff remains deferred until the repo names one concrete external desk or PSA target.
  3. Cross-Tenant Compare and Promotion v1 remains on the existing Spec 043 track as a refresh candidate rather than being reopened inside this hardening slice.