Review Generator¶
Path:
services/decision/review-generator/· Type: Consumer
The Review Generator consumes score-change events and builds evidence-backed review packets for human reviewers. Each packet bundles the decay score with contextual evidence so that reviewers can make informed access decisions without manual investigation.
Architecture¶
graph LR
K1[verity.scores.updated] --> RG[Review Generator]
RG --> PG[(PostgreSQL)]
RG --> K2[verity.reviews.created]
Processing Flow¶
sequenceDiagram
participant Kafka as verity.scores.updated
participant RG as Review Generator
participant PG as PostgreSQL
participant Out as verity.reviews.created
Kafka->>RG: Score update event
RG->>PG: Load grant, principal, asset details
RG->>RG: Build ReviewPacket with evidence
RG->>RG: Assign reviewer
RG->>PG: Persist review_packets row
RG->>Out: Publish review created event
ReviewPacket Structure¶
Each review packet contains the following:
| Field | Type | Description |
|---|---|---|
packet_id |
UUID | Unique identifier |
grant_id |
UUID | The grant under review |
principal_id |
UUID | The principal who holds the grant |
asset_id |
UUID | The asset being accessed |
score |
int | Current decay score (0–100) |
risk_level |
enum | CRITICAL, HIGH, MEDIUM, LOW |
sla_deadline |
datetime | Review must be completed by this time |
reviewer_id |
UUID | Assigned reviewer |
evidence_json |
JSON | Structured evidence (see below) |
status |
enum | PENDING, APPROVED, REVOKED, ESCALATED |
created_at |
datetime | Packet creation timestamp |
Evidence JSON¶
The evidence_json field contains four sections of supporting data:
{
"access_history": {
"last_access": "2024-11-15T09:23:00Z",
"days_inactive": 47,
"events_last_90d": 3,
"events_prior_90d": 42
},
"peer_comparison": {
"peer_group": "data-engineering",
"peer_p80_events": 28,
"principal_events": 3,
"deviation": 0.107
},
"org_context": {
"team_changed": false,
"project_ended": true,
"project_name": "Project Atlas",
"project_end_date": "2024-10-01"
},
"sensitivity_context": {
"sensitivity": "FINANCIAL",
"multiplier": 0.75,
"classification_source": "snowflake_tag"
}
}
Reviewer Assignment¶
Reviewers are assigned using a hierarchical fallback strategy:
flowchart TD
A[Score update received] --> B{Data owner defined?}
B -->|Yes| C[Assign to data owner]
B -->|No| D{Data steward defined?}
D -->|Yes| E[Assign to data steward]
D -->|No| F{Manager available?}
F -->|Yes| G[Assign to manager]
F -->|No| H[Assign to platform admin]
| Priority | Reviewer Role | Source |
|---|---|---|
| 1 | Data owner | Asset metadata (owner_id field) |
| 2 | Data steward | Asset metadata (steward_id field) |
| 3 | Manager | Principal's reporting hierarchy |
| 4 | Platform admin | Fallback — global admin pool |
Configuration¶
| Variable | Required | Default | Description |
|---|---|---|---|
REVIEW_KAFKA_BOOTSTRAP |
Yes | — | Kafka bootstrap servers |
REVIEW_CONSUMER_GROUP |
No | verity-review-generator |
Kafka consumer group ID |
REVIEW_DATABASE_URL |
Yes | — | PostgreSQL connection string |
REVIEW_SCORE_THRESHOLD |
No | 80 |
Score at or below which a review is created |
REVIEW_LOG_LEVEL |
No | INFO |
Python log level |
Observability¶
| Metric | Type | Description |
|---|---|---|
review_packets_created_total |
Counter | Review packets generated (by risk level) |
review_assignment_fallbacks_total |
Counter | Times a fallback reviewer was used |
review_evidence_build_duration_seconds |
Histogram | Time to assemble evidence JSON |