@onproper/cli 0.0.0-stage → 1.0.4
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.
- package/README.md +99 -2
- package/bin/proper +4 -0
- package/package.json +19 -3
- package/postinstall.js +84 -0
package/README.md
CHANGED
|
@@ -1,3 +1,100 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Proper
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Lightweight, Zero-Knowledge Change Data Capture (CDC) & Dispatcher for PostgreSQL.**
|
|
4
|
+
|
|
5
|
+
Proper is a blazing-fast, edge-first Go binary that monitors your PostgreSQL database in real-time and triggers local scripts or external webhooks the millisecond a row changes.
|
|
6
|
+
|
|
7
|
+
Designed for strict memory safety and enterprise compliance, it runs securely inside your own VPC. Your database credentials never leave your servers.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## ✨ Features
|
|
12
|
+
|
|
13
|
+
* **Zero-Knowledge Architecture:** Reads your database locally. No raw row data is ever transmitted to a third party.
|
|
14
|
+
* **Smart Polymorphic Dispatching:** Automatically routes actions to local scripts (`node handler.js`) or HTTP webhooks based on the target string.
|
|
15
|
+
* **Lock-Free Hot Reloading:** Update your `proper.config.yaml` and the engine hot-swaps your rules in memory using atomic pointers—zero restarts, zero dropped events.
|
|
16
|
+
* **Poison Pill Prevention:** Built-in exponential backoff retries. If a webhook or script repeatedly fails, the event is quarantined to a local Dead Letter Queue (`proper.dlq.log`) to protect the database stream.
|
|
17
|
+
* **Enterprise Audit Logging:** Automatically outputs a structured `JSONL` (JSON Lines) file of every success and failure, instantly ready for Datadog, Splunk, or ELK.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## ⚡️ Quick Start
|
|
22
|
+
|
|
23
|
+
Proper is designed to be deployed as a sidecar to your database using Docker.
|
|
24
|
+
|
|
25
|
+
### 1. Define Environment Variables
|
|
26
|
+
|
|
27
|
+
# Your local database connection (Requires logical replication enabled)
|
|
28
|
+
DATABASE_URL=postgres://root:password@host.docker.internal:5432/app_db?replication=database
|
|
29
|
+
|
|
30
|
+
# A unique identifier for this deployment (prevents replication slot collisions)
|
|
31
|
+
PROPER_PIPELINE_ID=pipe_local_dev
|
|
32
|
+
|
|
33
|
+
### 2. Define your triggers (`proper.config.yaml`)
|
|
34
|
+
|
|
35
|
+
triggers:
|
|
36
|
+
- id: notify_slack_on_large_discount
|
|
37
|
+
table: purchase_order
|
|
38
|
+
action: UPDATE
|
|
39
|
+
condition:
|
|
40
|
+
field: discount_rate
|
|
41
|
+
operator: gt
|
|
42
|
+
value: "0.40"
|
|
43
|
+
dispatch:
|
|
44
|
+
# Proper auto-detects webhooks vs local scripts
|
|
45
|
+
exec: "[https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX](https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXXXXXXXXXX)"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
### 3. Boot the Engine (`docker-compose.yml`)
|
|
49
|
+
|
|
50
|
+
version: '3.8'
|
|
51
|
+
services:
|
|
52
|
+
proper-agent:
|
|
53
|
+
image: proper/engine:latest
|
|
54
|
+
container_name: proper_agent
|
|
55
|
+
env_file:
|
|
56
|
+
- .env
|
|
57
|
+
volumes:
|
|
58
|
+
- ./proper.config.yaml:/proper/proper.config.yaml:ro
|
|
59
|
+
- ./proper.dlq.log:/proper/proper.dlq.log
|
|
60
|
+
- ./proper.audit.log:/proper/proper.audit.log
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
Run:
|
|
65
|
+
touch proper.dlq.log proper.audit.log && docker compose up -d
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## 📊 The JSONL Audit Trail
|
|
70
|
+
|
|
71
|
+
Proper defaults to writing a high-performance, structured audit log to `/proper/proper.audit.log`. Every execution drops a complete JSON object, allowing your security team to easily parse and query your data movement.
|
|
72
|
+
|
|
73
|
+
{
|
|
74
|
+
"trigger_id":"notify_slack_on_large_discount",
|
|
75
|
+
"target":"[https://hooks.slack.com/](https://hooks.slack.com/)...",
|
|
76
|
+
"status":"success",
|
|
77
|
+
"payload":{
|
|
78
|
+
"id": 4,
|
|
79
|
+
"email": "test@example.com",
|
|
80
|
+
"discount_rate": 0.50},
|
|
81
|
+
"timestamp":"2026-10-02T14:32:01Z"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## ☁️ Upgrading to Proper Cloud (SaaS)
|
|
88
|
+
|
|
89
|
+
Managing local YAML files and grepping text logs is fine for side projects, but enterprise compliance (like the **California Delete Act / SB 362**) requires a cryptographically secure chain of custody.
|
|
90
|
+
|
|
91
|
+
**Proper Cloud** acts as your immutable compliance ledger and control plane.
|
|
92
|
+
|
|
93
|
+
By simply adding a `PROPER_API_KEY` to your `.env` file, the open-source agent instantly upgrades:
|
|
94
|
+
|
|
95
|
+
1. **GitOps Sync:** It pushes your local YAML rules to the Cloud Dashboard for version control and one-click rollbacks.
|
|
96
|
+
2. **Visual Dashboard:** Manage your triggers, conditions, and webhooks via a clean web UI without touching code.
|
|
97
|
+
3. **Verified Telemetry:** The agent securely streams its execution batches to our Control Plane, separating them from the unverified local text files.
|
|
98
|
+
4. **Automated Compliance:** Generate legally binding Certificates of Erasure (PDFs) with a single click to prove to regulators that your fan-out deletions executed successfully across HubSpot, Stripe, and your internal DB.
|
|
99
|
+
|
|
100
|
+
*Proper Cloud is currently in early access.* **[Join the waitlist at onproper.com](https://www.onproper.com)**
|
package/bin/proper
ADDED
package/package.json
CHANGED
|
@@ -1,6 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onproper/cli",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "1.0.4",
|
|
4
|
+
"description": "The Zero-Trust Entity Orchestration & Compliance Engine",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"proper": "bin/proper"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"prepublishOnly": "cp ../README.md ./README.md",
|
|
11
|
+
"postinstall": "node postinstall.js"
|
|
12
|
+
},
|
|
13
|
+
"keywords": [
|
|
14
|
+
"cdc",
|
|
15
|
+
"postgres",
|
|
16
|
+
"compliance",
|
|
17
|
+
"webhook",
|
|
18
|
+
"proper"
|
|
19
|
+
],
|
|
20
|
+
"author": "Proper",
|
|
21
|
+
"license": "MIT"
|
|
6
22
|
}
|
package/postinstall.js
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
const os = require('os');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const https = require('https');
|
|
5
|
+
const { execSync } = require('child_process');
|
|
6
|
+
|
|
7
|
+
// 🔥 THE FIX: Dynamically read the version NPM just installed
|
|
8
|
+
const packageJson = require('./package.json');
|
|
9
|
+
const VERSION = `v${packageJson.version}`; // Translates "1.0.0" to "v1.0.0"
|
|
10
|
+
const REPO = 'vulsys/proper-release';
|
|
11
|
+
|
|
12
|
+
// 1. Map Node's OS/Arch to Go's OS/Arch
|
|
13
|
+
const platformMap = {
|
|
14
|
+
darwin: 'darwin',
|
|
15
|
+
linux: 'linux',
|
|
16
|
+
win32: 'windows'
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const archMap = {
|
|
20
|
+
x64: 'amd64',
|
|
21
|
+
arm64: 'arm64'
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const platform = platformMap[os.platform()];
|
|
25
|
+
const arch = archMap[os.arch()];
|
|
26
|
+
|
|
27
|
+
if (!platform || !arch) {
|
|
28
|
+
console.error(`❌ @onproper/cli does not support ${os.platform()} ${os.arch()}`);
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// 2. Build the exact GitHub Release URL
|
|
33
|
+
let binaryName = `proper-${platform}-${arch}`;
|
|
34
|
+
if (platform === 'windows') {
|
|
35
|
+
binaryName += '.exe';
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const downloadUrl = `https://github.com/${REPO}/releases/download/${VERSION}/${binaryName}`;
|
|
39
|
+
|
|
40
|
+
// 3. Prepare the destination folder
|
|
41
|
+
const binDir = path.join(__dirname, 'bin');
|
|
42
|
+
if (!fs.existsSync(binDir)) {
|
|
43
|
+
fs.mkdirSync(binDir);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const destFile = path.join(binDir, platform === 'windows' ? 'proper.exe' : 'proper');
|
|
47
|
+
|
|
48
|
+
// 4. Download the binary
|
|
49
|
+
console.log(`⬇️ Downloading Proper CDC Engine (${binaryName})...`);
|
|
50
|
+
|
|
51
|
+
https.get(downloadUrl, (res) => {
|
|
52
|
+
if (res.statusCode === 301 || res.statusCode === 302) {
|
|
53
|
+
// Follow GitHub's redirect to the actual AWS S3 bucket
|
|
54
|
+
https.get(res.headers.location, handleDownload).on('error', handleError);
|
|
55
|
+
} else {
|
|
56
|
+
handleDownload(res);
|
|
57
|
+
}
|
|
58
|
+
}).on('error', handleError);
|
|
59
|
+
|
|
60
|
+
function handleDownload(res) {
|
|
61
|
+
if (res.statusCode !== 200) {
|
|
62
|
+
console.error(`❌ Failed to download binary. Status Code: ${res.statusCode}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const fileStream = fs.createWriteStream(destFile);
|
|
67
|
+
res.pipe(fileStream);
|
|
68
|
+
|
|
69
|
+
fileStream.on('finish', () => {
|
|
70
|
+
fileStream.close();
|
|
71
|
+
|
|
72
|
+
// 5. Make it executable for Mac/Linux
|
|
73
|
+
if (platform !== 'windows') {
|
|
74
|
+
execSync(`chmod +x ${destFile}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log('✅ Proper installed successfully. Run `proper init` to begin.');
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function handleError(err) {
|
|
82
|
+
console.error(`❌ Download error: ${err.message}`);
|
|
83
|
+
process.exit(1);
|
|
84
|
+
}
|