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.
- package/LICENCE +1 -0
- package/LICENSE +201 -21
- package/README.md +213 -203
- package/bin/cli.js +56 -56
- package/package.json +39 -39
- package/skills/nightpay/SKILL.md +141 -105
- package/skills/nightpay/contracts/receipt.compact +197 -195
- package/skills/nightpay/openclaw-fragment.json +20 -20
- package/skills/nightpay/rules/content-safety.md +187 -187
- package/skills/nightpay/rules/escrow-safety.md +140 -139
- package/skills/nightpay/rules/privacy-first.md +30 -30
- package/skills/nightpay/rules/receipt-format.md +45 -45
- package/skills/nightpay/scripts/bounty-board.sh +325 -325
- package/skills/nightpay/scripts/gateway.sh +83 -26
- package/skills/nightpay/scripts/mip003-server.sh +282 -28
- package/skills/nightpay/scripts/update-blocklist.sh +194 -194
|
@@ -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 |
|