nightpay 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nightpay might be problematic. Click here for more details.

@@ -1,187 +1,187 @@
1
- # Content Safety Rule
2
-
3
- ## Principle: Classify-Then-Forget
4
-
5
- The gateway sees the plaintext job description **in memory only** — long enough to
6
- classify it, then immediately hashes it. The plaintext is never logged, persisted,
7
- or transmitted. This preserves funder privacy while enforcing safety.
8
-
9
- ## Three-Layer Defense
10
-
11
- ```
12
- Layer 1: Live rules file (auto-updated by update-blocklist.sh)
13
- |
14
- v if no rules file exists
15
- Layer 2: Hardcoded fallback (14 patterns baked into gateway.sh)
16
- |
17
- v if local rules pass
18
- Layer 3: External moderation API (AI-powered classification, optional)
19
- ```
20
-
21
- Every bounty must pass **all available layers** before a commitment is created.
22
-
23
- ## What is Rejected
24
-
25
- Any bounty whose job description matches one or more of these categories:
26
-
27
- | Category | Examples |
28
- |---|---|
29
- | **Child sexual abuse material (CSAM)** | Any content sexualizing minors |
30
- | **Violence / assassination** | "Kill", "harm", "attack [person]", physical threats |
31
- | **Weapons of mass destruction** | Biological, chemical, nuclear, radiological |
32
- | **Human trafficking / slavery** | Forced labor, organ harvesting, exploitation |
33
- | **Terrorism / extremism** | Recruitment, planning, financing of terror acts |
34
- | **Non-consensual intimate imagery** | Deepfakes, revenge content, sextortion |
35
- | **Financial fraud** | Money laundering, counterfeiting, sanctions evasion |
36
- | **Critical infrastructure attack** | Power grids, water systems, hospitals, elections |
37
- | **Doxxing / stalking** | Identifying, tracking, or surveilling private individuals |
38
- | **Drug manufacturing** | Synthesis of controlled substances (not research) |
39
-
40
- This list is not exhaustive. The live rules file and external API extend coverage.
41
-
42
- ## Enforcement Points
43
-
44
- Two gates, defense-in-depth:
45
-
46
- 1. **`post-bounty`** — before commitment hash is created. Rejected bounties never
47
- produce a commitment and no funds move.
48
- 2. **`hire-and-pay`** — before Masumi escrow is created. Catches descriptions that
49
- were committed outside the gateway (e.g. direct circuit call).
50
-
51
- ## What Happens on Rejection
52
-
53
- - The gateway prints a `REJECTED` status with the matched category
54
- - No commitment is created, no hash is emitted, no funds move
55
- - The plaintext description is **not logged** — only the category name
56
- - Exit code 2 (distinct from validation errors which use exit code 1)
57
-
58
- ## Auto-Updating Rules (update-blocklist.sh)
59
-
60
- The static regex list goes stale. `update-blocklist.sh` keeps it current:
61
-
62
- ```bash
63
- # Run every 6 hours via cron
64
- 0 */6 * * * /path/to/scripts/update-blocklist.sh
65
- ```
66
-
67
- ### Sources
68
-
69
- | Source | What It Provides | Update Frequency |
70
- |---|---|---|
71
- | **Base rules** (hardcoded) | 14 core patterns for the 10 categories | Static — code changes only |
72
- | **stamparm/maltrail** | Malicious campaign names, known-bad keywords | Daily (GitHub raw) |
73
- | **Community complaints** | Patterns derived from user reports that hit freeze threshold | Real-time (on flag) |
74
- | **Operator custom rules** | `~/.nightpay/safety/custom-rules.json` | Operator-managed |
75
-
76
- ### Custom Rules Format
77
-
78
- Operators can add domain-specific patterns in `~/.nightpay/safety/custom-rules.json`:
79
-
80
- ```json
81
- {
82
- "rules": [
83
- {"category": "scam", "pattern": "\\b(ponzi|pyramid)\\b.*\\b(scheme|invest)\\b"},
84
- {"category": "gambling", "pattern": "\\b(casino|betting|slots)\\b"}
85
- ]
86
- }
87
- ```
88
-
89
- Invalid regex patterns are skipped with a warning, not fatal.
90
-
91
- ### Output
92
-
93
- Rules are merged, deduplicated, and written atomically to:
94
- ```
95
- ~/.nightpay/safety/safety-rules.json
96
- ```
97
-
98
- The gateway hot-loads this file on every `safety_check()` call — no restart required.
99
-
100
- ## Community Complaint System
101
-
102
- Anyone can report a bounty they believe is harmful:
103
-
104
- ```bash
105
- # Report a bounty (REPORTER_ID is hashed for privacy-preserving dedup)
106
- REPORTER_ID=alice ./bounty-board.sh report <commitment> <category> [reason]
107
-
108
- # View complaints for a specific bounty
109
- ./bounty-board.sh reports <commitment>
110
-
111
- # View all flagged bounties
112
- ./bounty-board.sh reports
113
- ```
114
-
115
- ### Valid Report Categories
116
-
117
- `csam`, `violence`, `weapons_of_mass_destruction`, `human_trafficking`,
118
- `terrorism`, `ncii`, `financial_fraud`, `infrastructure_attack`,
119
- `doxxing`, `drug_manufacturing`, `other`
120
-
121
- ### Auto-Freeze
122
-
123
- When a bounty reaches **3 complaints** (configurable via `COMPLAINT_FREEZE_THRESHOLD`):
124
-
125
- 1. Bounty status changes from `active` to `flagged`
126
- 2. Flagged bounties are hidden from `list` (no longer discoverable)
127
- 3. The complaint data is exported to `community-reports.json`
128
- 4. On next `update-blocklist.sh` run, complaint patterns feed back into rules
129
-
130
- ### Privacy Guarantees for Reporters
131
-
132
- - Reporter identity is **SHA-256 hashed** before storage — only used for dedup
133
- - The `REPORTER_ID` env var is never persisted in the database
134
- - Complaint reasons are stored but the bounty description is not (it was never stored)
135
- - Reporters cannot see other reporters' identities
136
-
137
- ### Feedback Loop
138
-
139
- ```
140
- User reports bounty → complaint stored in SQLite
141
- → threshold hit → bounty auto-frozen
142
- → complaint categories exported to community-reports.json
143
- → update-blocklist.sh reads community-reports.json
144
- → trending complaint categories become new regex rules
145
- → gateway.sh loads updated safety-rules.json
146
- → future similar bounties blocked at post-bounty gate
147
- ```
148
-
149
- ## External Moderation API (Optional)
150
-
151
- Set `CONTENT_SAFETY_URL` to enable AI-powered classification:
152
-
153
- ```
154
- CONTENT_SAFETY_URL=http://localhost:8080/v1/classify
155
- ```
156
-
157
- The gateway sends a POST with `{"text": "<job_description>"}` and expects:
158
- ```json
159
- {"safe": false, "category": "violence", "confidence": 0.97}
160
- ```
161
-
162
- If the API is unavailable, layers 1-2 still protect. The API is additive.
163
- The API response is **not logged** — only the boolean decision.
164
-
165
- ### Recommended External APIs
166
-
167
- - **Anthropic content classification** — context-aware, low false positive rate
168
- - **OpenAI moderation endpoint** — free tier available, 11 categories
169
- - **Self-hosted models** — full control, no data leaves your infrastructure
170
-
171
- ## Privacy Guarantee
172
-
173
- - Job descriptions are **never logged**, even rejected ones
174
- - Only the rejection category name appears in output
175
- - The external API call uses `--max-time 5` — no hanging on moderation
176
- - After classification, the plaintext variable is unset in the shell
177
- - Reporter identities are hashed — complaints are pseudonymous
178
-
179
- ## Configuration
180
-
181
- | Env Var | Default | Purpose |
182
- |---|---|---|
183
- | `CONTENT_SAFETY_URL` | (empty) | External moderation API endpoint |
184
- | `SAFETY_RULES_FILE` | `~/.nightpay/safety/safety-rules.json` | Live rules file path |
185
- | `COMPLAINT_FREEZE_THRESHOLD` | `3` | Complaints before auto-freeze |
186
- | `REPORTER_ID` | `anonymous` | Reporter identity (hashed for dedup) |
187
- | `BOARD_HMAC_KEY` | (required) | Board integrity HMAC key |
1
+ # Content Safety Rule
2
+
3
+ ## Principle: Classify-Then-Forget
4
+
5
+ The gateway sees the plaintext job description **in memory only** — long enough to
6
+ classify it, then immediately hashes it. The plaintext is never logged, persisted,
7
+ or transmitted. This preserves funder privacy while enforcing safety.
8
+
9
+ ## Three-Layer Defense
10
+
11
+ ```
12
+ Layer 1: Live rules file (auto-updated by update-blocklist.sh)
13
+ |
14
+ v if no rules file exists
15
+ Layer 2: Hardcoded fallback (14 patterns baked into gateway.sh)
16
+ |
17
+ v if local rules pass
18
+ Layer 3: External moderation API (AI-powered classification, optional)
19
+ ```
20
+
21
+ Every bounty must pass **all available layers** before a commitment is created.
22
+
23
+ ## What is Rejected
24
+
25
+ Any bounty whose job description matches one or more of these categories:
26
+
27
+ | Category | Examples |
28
+ |---|---|
29
+ | **Child sexual abuse material (CSAM)** | Any content sexualizing minors |
30
+ | **Violence / assassination** | "Kill", "harm", "attack [person]", physical threats |
31
+ | **Weapons of mass destruction** | Biological, chemical, nuclear, radiological |
32
+ | **Human trafficking / slavery** | Forced labor, organ harvesting, exploitation |
33
+ | **Terrorism / extremism** | Recruitment, planning, financing of terror acts |
34
+ | **Non-consensual intimate imagery** | Deepfakes, revenge content, sextortion |
35
+ | **Financial fraud** | Money laundering, counterfeiting, sanctions evasion |
36
+ | **Critical infrastructure attack** | Power grids, water systems, hospitals, elections |
37
+ | **Doxxing / stalking** | Identifying, tracking, or surveilling private individuals |
38
+ | **Drug manufacturing** | Synthesis of controlled substances (not research) |
39
+
40
+ This list is not exhaustive. The live rules file and external API extend coverage.
41
+
42
+ ## Enforcement Points
43
+
44
+ Two gates, defense-in-depth:
45
+
46
+ 1. **`post-bounty`** — before commitment hash is created. Rejected bounties never
47
+ produce a commitment and no funds move.
48
+ 2. **`hire-and-pay`** — before Masumi escrow is created. Catches descriptions that
49
+ were committed outside the gateway (e.g. direct circuit call).
50
+
51
+ ## What Happens on Rejection
52
+
53
+ - The gateway prints a `REJECTED` status with the matched category
54
+ - No commitment is created, no hash is emitted, no funds move
55
+ - The plaintext description is **not logged** — only the category name
56
+ - Exit code 2 (distinct from validation errors which use exit code 1)
57
+
58
+ ## Auto-Updating Rules (update-blocklist.sh)
59
+
60
+ The static regex list goes stale. `update-blocklist.sh` keeps it current:
61
+
62
+ ```bash
63
+ # Run every 6 hours via cron
64
+ 0 */6 * * * /path/to/scripts/update-blocklist.sh
65
+ ```
66
+
67
+ ### Sources
68
+
69
+ | Source | What It Provides | Update Frequency |
70
+ |---|---|---|
71
+ | **Base rules** (hardcoded) | 14 core patterns for the 10 categories | Static — code changes only |
72
+ | **stamparm/maltrail** | Malicious campaign names, known-bad keywords | Daily (GitHub raw) |
73
+ | **Community complaints** | Patterns derived from user reports that hit freeze threshold | Real-time (on flag) |
74
+ | **Operator custom rules** | `~/.nightpay/safety/custom-rules.json` | Operator-managed |
75
+
76
+ ### Custom Rules Format
77
+
78
+ Operators can add domain-specific patterns in `~/.nightpay/safety/custom-rules.json`:
79
+
80
+ ```json
81
+ {
82
+ "rules": [
83
+ {"category": "scam", "pattern": "\\b(ponzi|pyramid)\\b.*\\b(scheme|invest)\\b"},
84
+ {"category": "gambling", "pattern": "\\b(casino|betting|slots)\\b"}
85
+ ]
86
+ }
87
+ ```
88
+
89
+ Invalid regex patterns are skipped with a warning, not fatal.
90
+
91
+ ### Output
92
+
93
+ Rules are merged, deduplicated, and written atomically to:
94
+ ```
95
+ ~/.nightpay/safety/safety-rules.json
96
+ ```
97
+
98
+ The gateway hot-loads this file on every `safety_check()` call — no restart required.
99
+
100
+ ## Community Complaint System
101
+
102
+ Anyone can report a bounty they believe is harmful:
103
+
104
+ ```bash
105
+ # Report a bounty (REPORTER_ID is hashed for privacy-preserving dedup)
106
+ REPORTER_ID=alice ./bounty-board.sh report <commitment> <category> [reason]
107
+
108
+ # View complaints for a specific bounty
109
+ ./bounty-board.sh reports <commitment>
110
+
111
+ # View all flagged bounties
112
+ ./bounty-board.sh reports
113
+ ```
114
+
115
+ ### Valid Report Categories
116
+
117
+ `csam`, `violence`, `weapons_of_mass_destruction`, `human_trafficking`,
118
+ `terrorism`, `ncii`, `financial_fraud`, `infrastructure_attack`,
119
+ `doxxing`, `drug_manufacturing`, `other`
120
+
121
+ ### Auto-Freeze
122
+
123
+ When a bounty reaches **3 complaints** (configurable via `COMPLAINT_FREEZE_THRESHOLD`):
124
+
125
+ 1. Bounty status changes from `active` to `flagged`
126
+ 2. Flagged bounties are hidden from `list` (no longer discoverable)
127
+ 3. The complaint data is exported to `community-reports.json`
128
+ 4. On next `update-blocklist.sh` run, complaint patterns feed back into rules
129
+
130
+ ### Privacy Guarantees for Reporters
131
+
132
+ - Reporter identity is **SHA-256 hashed** before storage — only used for dedup
133
+ - The `REPORTER_ID` env var is never persisted in the database
134
+ - Complaint reasons are stored but the bounty description is not (it was never stored)
135
+ - Reporters cannot see other reporters' identities
136
+
137
+ ### Feedback Loop
138
+
139
+ ```
140
+ User reports bounty → complaint stored in SQLite
141
+ → threshold hit → bounty auto-frozen
142
+ → complaint categories exported to community-reports.json
143
+ → update-blocklist.sh reads community-reports.json
144
+ → trending complaint categories become new regex rules
145
+ → gateway.sh loads updated safety-rules.json
146
+ → future similar bounties blocked at post-bounty gate
147
+ ```
148
+
149
+ ## External Moderation API (Optional)
150
+
151
+ Set `CONTENT_SAFETY_URL` to enable AI-powered classification:
152
+
153
+ ```
154
+ CONTENT_SAFETY_URL=http://localhost:8080/v1/classify
155
+ ```
156
+
157
+ The gateway sends a POST with `{"text": "<job_description>"}` and expects:
158
+ ```json
159
+ {"safe": false, "category": "violence", "confidence": 0.97}
160
+ ```
161
+
162
+ If the API is unavailable, layers 1-2 still protect. The API is additive.
163
+ The API response is **not logged** — only the boolean decision.
164
+
165
+ ### Recommended External APIs
166
+
167
+ - **Anthropic content classification** — context-aware, low false positive rate
168
+ - **OpenAI moderation endpoint** — free tier available, 11 categories
169
+ - **Self-hosted models** — full control, no data leaves your infrastructure
170
+
171
+ ## Privacy Guarantee
172
+
173
+ - Job descriptions are **never logged**, even rejected ones
174
+ - Only the rejection category name appears in output
175
+ - The external API call uses `--max-time 5` — no hanging on moderation
176
+ - After classification, the plaintext variable is unset in the shell
177
+ - Reporter identities are hashed — complaints are pseudonymous
178
+
179
+ ## Configuration
180
+
181
+ | Env Var | Default | Purpose |
182
+ |---|---|---|
183
+ | `CONTENT_SAFETY_URL` | (empty) | External moderation API endpoint |
184
+ | `SAFETY_RULES_FILE` | `~/.nightpay/safety/safety-rules.json` | Live rules file path |
185
+ | `COMPLAINT_FREEZE_THRESHOLD` | `3` | Complaints before auto-freeze |
186
+ | `REPORTER_ID` | `anonymous` | Reporter identity (hashed for dedup) |
187
+ | `BOARD_HMAC_KEY` | (required) | Board integrity HMAC key |