You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Turn repeated scan observations into stable, tenant-isolated, auditable finding lifecycles and three deterministic pattern types. This is PR 1 of 5 and the evidence foundation for all later automation.
Scope
Scan completeness contract
Record a versioned outcome for every scheduled rule and required collector:
SUCCESS, EMPTY_SUCCESS, PERMISSION_DENIED, TIMEOUT, FAILED, or NOT_APPLICABLE.
Store rule version, collector version, inventory boundary, tenant, subscription, timestamps, and error category.
A scan may be operationally completed while individual rules are incomplete, but incomplete rules must never resolve findings.
A finding may become RESOLVED only when its rule and required collectors succeeded over the same authorised inventory boundary.
Stable finding fingerprint
Derive the fingerprint from tenant ID, subscription ID, normalized Azure resource ID, rule ID, and a versioned rule-owned evidence key. Define normalization and fingerprint schema versions. Never use mutable display names or finding prose.
Pattern records and pattern-to-scan/finding evidence references.
An idempotency record preventing a completed scan from being applied twice.
Lifecycle states: OPEN, RESOLVED, ACCEPTED, SUPPRESSED, and REOPENED. Preserve raw finding instances and append-only transition history.
Deterministic patterns
Implement only persistent finding, cross-resource recurrence, and reopened finding. Store threshold values and algorithm version with every published pattern. No LLM creates or publishes patterns.
APIs
Use the repository's explicitly documented API-versioning convention:
GET /api/v1/patterns
GET /api/v1/patterns/{pattern_id}
Enforce server-side tenant and subscription authorization on every query. Keep existing APIs backward compatible.
Required implementation boundaries
Routes perform authentication, authorization, schema parsing, and status mapping only.
Services own lifecycle and pattern transitions.
Repositories own transactional PostgreSQL operations.
Lifecycle update and completed-scan persistence occur in one transaction.
Concurrent processing uses row locks or equivalent conflict protection.
Failed, partial, timed-out, or permission-incomplete evidence fails closed.
Measurable acceptance criteria
Replaying the same scan 100 times produces exactly one lifecycle application and no duplicate transition.
Two concurrent processors applying the same scan produce the same result as one processor.
An absent finding resolves only after a successful relevant rule/collector outcome.
PERMISSION_DENIED, TIMEOUT, FAILED, missing outcome, or incomplete inventory never resolves a finding.
A resolved fingerprint seen again becomes REOPENED and increments reopen_count exactly once.
Tenant A cannot read Tenant B patterns; cross-subscription data cannot combine unless explicitly authorised.
Every pattern cites existing scan and finding IDs and exposes threshold and algorithm versions.
Upgrade from current schema and downgrade back succeed against a populated test database.
Objective
Turn repeated scan observations into stable, tenant-isolated, auditable finding lifecycles and three deterministic pattern types. This is PR 1 of 5 and the evidence foundation for all later automation.
Scope
Scan completeness contract
Record a versioned outcome for every scheduled rule and required collector:
SUCCESS,EMPTY_SUCCESS,PERMISSION_DENIED,TIMEOUT,FAILED, orNOT_APPLICABLE.RESOLVEDonly when its rule and required collectors succeeded over the same authorised inventory boundary.Stable finding fingerprint
Derive the fingerprint from tenant ID, subscription ID, normalized Azure resource ID, rule ID, and a versioned rule-owned evidence key. Define normalization and fingerprint schema versions. Never use mutable display names or finding prose.
Persistence
Add reversible Alembic migrations for:
scan_rule_outcomesand collector outcomes.finding_lifecyclescontaining fingerprint, first/last seen, occurrence count, consecutive successful-scan count, state, reopen count, and optimistic/row-locking metadata.Lifecycle states:
OPEN,RESOLVED,ACCEPTED,SUPPRESSED, andREOPENED. Preserve raw finding instances and append-only transition history.Deterministic patterns
Implement only persistent finding, cross-resource recurrence, and reopened finding. Store threshold values and algorithm version with every published pattern. No LLM creates or publishes patterns.
APIs
Use the repository's explicitly documented API-versioning convention:
GET /api/v1/patternsGET /api/v1/patterns/{pattern_id}Enforce server-side tenant and subscription authorization on every query. Keep existing APIs backward compatible.
Required implementation boundaries
Measurable acceptance criteria
PERMISSION_DENIED,TIMEOUT,FAILED, missing outcome, or incomplete inventory never resolves a finding.REOPENEDand incrementsreopen_countexactly once.Delivery evidence attached to PR
Deferred
Deployment-wave analysis, statistical attribution, organization dashboards, and LLM-generated patterns.
Dependencies and handoff
No dependency. #312 begins only after this migration and lifecycle contract are merged and observed in read-only mode.
Mandatory safety and automation checklist
Evidence integrity
Transactions and retries
Isolation and authorization
Tests and proof
Exit gate