openspec: scan-limits-gating change — paid-order gating + daily/IP alert caps (no gateway)

This commit is contained in:
2026-08-08 09:22:09 +10:00
parent 31174d41e6
commit 92ccf3d0f3
7 changed files with 132 additions and 0 deletions

View File

@@ -0,0 +1,30 @@
## ADDED Requirements
### Requirement: Paid-order gating
When a tag has a linked order (`order_id` not null) whose status is not `paid`, scans SHALL be recorded but no alert SMS SHALL be sent. Tags without a linked order SHALL still alert (transitional).
#### Scenario: Lapsed order
- **WHEN** a scan arrives on a tag whose order status is `lapsed` or `pending`
- **THEN** the scan is recorded with `alert_sent = false` and no SMS is sent
#### Scenario: Paid order
- **WHEN** a scan arrives on a tag whose order is `paid`
- **THEN** normal alert rules apply
#### Scenario: No order yet
- **WHEN** a scan arrives on a tag with no linked order
- **THEN** normal alert rules apply (transitional behaviour)
### Requirement: Per-tag daily alert cap
A tag SHALL alert at most N times in any 24-hour window (N configurable, default 5). Excess scans are recorded without alerts.
#### Scenario: Cap reached
- **WHEN** a tag has already alerted N times in the last 24 h
- **THEN** further scans are recorded but no SMS is sent
### Requirement: Per-IP hourly rate limit
A scanner IP SHALL trigger at most M alerts per hour (M configurable, default 10). Excess alerts from the same IP are suppressed.
#### Scenario: Rate exceeded
- **WHEN** an IP has triggered M alerts in the last hour
- **THEN** further scan alerts from that IP are suppressed (scans still recorded)

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Paid-order gating in alert decision
The alert decision (`shouldAlert`) SHALL return false when the tag's linked order exists and is not `paid`.
#### Scenario: Lapsed tag scan
- **WHEN** a scan arrives on a tag with a non-paid order
- **THEN** `shouldAlert` returns false (record only)
### Requirement: Cap checks in alert decision
The alert decision SHALL respect the per-tag daily cap and per-IP hourly rate limit.
#### Scenario: Over cap
- **WHEN** the daily or hourly counter is exceeded
- **THEN** `shouldAlert` returns false (record only)