getculpa 1.0.10 → 1.1.0

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/LICENSE CHANGED
@@ -1,43 +1,43 @@
1
- Culpa — proprietary software licence
2
- ====================================
3
-
4
- Copyright (c) 2026 Myaigi AI Labs (Proprietary) Limited.
5
- All rights reserved.
6
-
7
- Culpa is proprietary software. It is licensed, not sold.
8
-
9
- Your use of this package, the `getculpa` and `culpa` commands it installs, the
10
- binaries it downloads, and the Culpa container images it runs is governed by
11
- the Culpa End User Licence Agreement ("EULA") between you and Myaigi AI Labs
12
- (Proprietary) Limited.
13
-
14
- Licensor: Myaigi AI Labs (Proprietary) Limited
15
- Registration number 2025/688531/07
16
- 121 Senior Drive, Randburg, Gauteng, 2195, South Africa
17
- Product: Culpa
18
- Governing law: Republic of South Africa
19
-
20
- The full End User Licence Agreement ships WITH the product: it is shown at
21
- first launch and is readable any time at /docs/terms-of-use in the app, and
22
- as client_docs/terms-of-use.md in the source. You do not need to ask for it.
23
-
24
- Except as the EULA expressly permits, you may not copy, modify, merge,
25
- publish, distribute, sublicense, sell, rent, lease, reverse engineer, or
26
- create derivative works of the Software, and you may not remove or alter any
27
- proprietary notice in it.
28
-
29
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
- IMPLIED, TO THE FULLEST EXTENT PERMITTED BY LAW. The EULA governs warranties,
31
- liability, and your statutory rights, and prevails over this notice wherever
32
- the two differ. Nothing here limits any right you have under applicable
33
- consumer law that cannot lawfully be excluded.
34
-
35
- This package downloads and installs additional Culpa components at install
36
- time and at update time, from Culpa's official release channel, with each
37
- artifact verified by checksum before it is used.
38
-
39
- Third-party open-source components distributed with or downloaded by Culpa
40
- remain under their own licences; those licences continue to apply to them and
41
- nothing in this notice restricts rights granted by them.
42
-
43
- Legal notices and licensing questions: info@myaigi.ai
1
+ Culpa — proprietary software licence
2
+ ====================================
3
+
4
+ Copyright (c) 2026 Myaigi AI Labs (Proprietary) Limited.
5
+ All rights reserved.
6
+
7
+ Culpa is proprietary software. It is licensed, not sold.
8
+
9
+ Your use of this package, the `getculpa` and `culpa` commands it installs, the
10
+ binaries it downloads, and the Culpa container images it runs is governed by
11
+ the Culpa End User Licence Agreement ("EULA") between you and Myaigi AI Labs
12
+ (Proprietary) Limited.
13
+
14
+ Licensor: Myaigi AI Labs (Proprietary) Limited
15
+ Registration number 2025/688531/07
16
+ 121 Senior Drive, Randburg, Gauteng, 2195, South Africa
17
+ Product: Culpa
18
+ Governing law: Republic of South Africa
19
+
20
+ The full End User Licence Agreement ships WITH the product: it is shown at
21
+ first launch and is readable any time at /docs/terms-of-use in the app, and
22
+ as client_docs/terms-of-use.md in the source. You do not need to ask for it.
23
+
24
+ Except as the EULA expressly permits, you may not copy, modify, merge,
25
+ publish, distribute, sublicense, sell, rent, lease, reverse engineer, or
26
+ create derivative works of the Software, and you may not remove or alter any
27
+ proprietary notice in it.
28
+
29
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
30
+ IMPLIED, TO THE FULLEST EXTENT PERMITTED BY LAW. The EULA governs warranties,
31
+ liability, and your statutory rights, and prevails over this notice wherever
32
+ the two differ. Nothing here limits any right you have under applicable
33
+ consumer law that cannot lawfully be excluded.
34
+
35
+ This package downloads and installs additional Culpa components at install
36
+ time and at update time, from Culpa's official release channel, with each
37
+ artifact verified by checksum before it is used.
38
+
39
+ Third-party open-source components distributed with or downloaded by Culpa
40
+ remain under their own licences; those licences continue to apply to them and
41
+ nothing in this notice restricts rights granted by them.
42
+
43
+ Legal notices and licensing questions: info@myaigi.ai
package/README.md CHANGED
@@ -5,11 +5,14 @@ money went, across models, features and users, on your own machine.
5
5
 
6
6
  **`npm i -g getculpa` provisions the full Culpa install — the same files,
7
7
  shortcuts, and registration the Windows installer lays down — and starts
8
- nothing.** `getculpa` is what wakes the stack up. On npm 12 or newer, npm
9
- blocks install scripts by default: install with
8
+ nothing.** `getculpa` is what wakes the stack up. npm 12 and newer block
9
+ install scripts by default (a Homebrew-installed npm 11.19 on macOS has been
10
+ seen doing the same): install with
10
11
  `npm i -g --allow-scripts=getculpa getculpa` (or run
11
12
  `npm config set allow-scripts=getculpa --location=user` once). If `getculpa`
12
- says Culpa was never provisioned, that is why.
13
+ says Culpa was never provisioned, that is why. On macOS the production traffic
14
+ collector is not started automatically yet; the coding-tool scan, the gateway
15
+ route, imports and the relay work as documented.
13
16
 
14
17
  - `getculpa` / `getculpa start` — start (or resume) the Culpa stack
15
18
  - `getculpa stop` — stop the running stack (`docker compose stop`; recorded data is kept)
@@ -1,137 +1,137 @@
1
- # CF18 (D-088 items 4/5) - the capture collector's lifecycle on a Windows
2
- # host install. ONE implementation; install-culpa.ps1, launch-culpa.ps1 and
3
- # uninstall-culpa.ps1 each make a one-line call, so the three can never drift.
4
- #
5
- # culpa-collector.ps1 -Start [-MailboxUrl http://127.0.0.1:4545]
6
- # culpa-collector.ps1 -Stop
7
- # culpa-collector.ps1 -Status
8
- #
9
- # WHY A HOST PROCESS AND NOT A COMPOSE SERVICE: collectord binds 127.0.0.1
10
- # ONLY, by design (D-082 privacy boundary - raw observation material crosses
11
- # loopback IPC and nothing else). Docker port-publishing cannot expose a
12
- # loopback-bound process, so a containerized collector beside the server is
13
- # unreachable by an app running on the host - the common case this installer
14
- # serves. The native binary on the host IS the loopback the app shares.
15
- # (Containerized apps use deploy/capture/capture-compose.yml's netns-sharing
16
- # sidecar instead; `culpa connect` prints which applies.)
17
- #
18
- # The token authenticates the collector to the mailbox target. Against the
19
- # local culpa-api it is not currently checked (capture is never gated,
20
- # D-031 section 7), but collectord requires one at boot and a future hosted target
21
- # does check it - so a real one is generated once and persisted beside the
22
- # install, never a hardcoded placeholder.
23
-
24
- param(
25
- [switch]$Start,
26
- [switch]$Stop,
27
- [switch]$Status,
28
- [string]$MailboxUrl = "http://127.0.0.1:4545",
29
- # CodeRabbit PR#16: overridable when 4752 is taken on the host
30
- [int]$Port = 4752
31
- )
32
-
33
- $ErrorActionPreference = "Stop"
34
- $AppDir = $PSScriptRoot
35
- $Exe = Join-Path $AppDir "culpa-collectord-win32-x64.exe"
36
- $RegisterMjs = Join-Path $AppDir "register.mjs"
37
- $PidFile = Join-Path $AppDir "collector.pid"
38
- $TokenFile = Join-Path $AppDir "collector-token.txt"
39
- $LogFile = Join-Path $AppDir "collector.log"
40
-
41
- function Get-RunningCollectorId {
42
- if (-not (Test-Path $PidFile)) { return $null }
43
- $savedPid = (Get-Content $PidFile -ErrorAction SilentlyContinue | Select-Object -First 1)
44
- # CodeRabbit PR#16: a corrupt PID file (partial write, manual edit) used to
45
- # TERMINATE the script - Get-Process's [int] binding fails under
46
- # ErrorActionPreference=Stop and SilentlyContinue does not cover binding
47
- # errors. Parse defensively: garbage means "not running", never a crash.
48
- $parsedPid = 0
49
- if (-not [int]::TryParse("$savedPid", [ref]$parsedPid) -or $parsedPid -le 0) { return $null }
50
- $proc = Get-Process -Id $parsedPid -ErrorAction SilentlyContinue
51
- # PID reuse guard: only claim it is ours if the image name matches
52
- if ($proc -and $proc.ProcessName -like "culpa-collectord*") { return $proc.Id }
53
- return $null
54
- }
55
-
56
- if ($Status) {
57
- $running = Get-RunningCollectorId
58
- if ($running) { Write-Host "collector: running (pid $running, port $Port)" }
59
- else { Write-Host "collector: not running" }
60
- exit 0
61
- }
62
-
63
- if ($Stop) {
64
- $running = Get-RunningCollectorId
65
- if ($running) {
66
- Stop-Process -Id $running -Force -ErrorAction SilentlyContinue
67
- Write-Host "collector: stopped (pid $running)"
68
- } else {
69
- Write-Host "collector: was not running"
70
- }
71
- Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
72
- exit 0
73
- }
74
-
75
- if (-not $Start) {
76
- Write-Host "usage: culpa-collector.ps1 -Start [-MailboxUrl <url>] | -Stop | -Status"
77
- exit 2
78
- }
79
-
80
- # -- Start --------------------------------------------------------------------
81
- if (-not (Test-Path $Exe)) {
82
- # an older zip layout without the capture plane - say so, never fail the
83
- # caller's install; the stack itself is unaffected
84
- Write-Host "collector: $((Split-Path $Exe -Leaf)) not present in this package - skipping capture setup" -ForegroundColor Yellow
85
- exit 0
86
- }
87
-
88
- $existing = Get-RunningCollectorId
89
- if ($existing) {
90
- Write-Host "collector: already running (pid $existing)"
91
- exit 0
92
- }
93
-
94
- if (-not (Test-Path $TokenFile)) {
95
- # 64 hex chars from the cryptographic RNG; persisted so restarts keep the
96
- # same credential (a hosted mailbox target checks it)
97
- $bytes = New-Object byte[] 32
98
- [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
99
- ($bytes | ForEach-Object { $_.ToString("x2") }) -join "" | Set-Content $TokenFile -NoNewline
100
- }
101
- $token = Get-Content $TokenFile -Raw
102
-
103
- $env:CULPA_MAILBOX_URL = $MailboxUrl
104
- $env:CULPA_MAILBOX_TOKEN = $token
105
- $env:CULPA_COLLECTOR_PORT = "$Port"
106
- $proc = Start-Process -FilePath $Exe -WindowStyle Hidden -PassThru `
107
- -RedirectStandardOutput $LogFile -RedirectStandardError "$LogFile.err"
108
- Set-Content $PidFile $proc.Id
109
-
110
- # bounded readiness wait: collectord prints "LISTENING <port>" on stdout
111
- $ready = $false
112
- for ($i = 0; $i -lt 20; $i++) {
113
- Start-Sleep -Milliseconds 250
114
- if ((Test-Path $LogFile) -and (Select-String -Path $LogFile -Pattern "LISTENING" -Quiet)) { $ready = $true; break }
115
- if ($proc.HasExited) { break }
116
- }
117
- if (-not $ready) {
118
- $detail = if (Test-Path "$LogFile.err") { Get-Content "$LogFile.err" -Raw } else { "(no log)" }
119
- Write-Host "collector: failed to start - capture is OFF, everything else still works." -ForegroundColor Yellow
120
- Write-Host " $($detail.Trim())" -ForegroundColor Yellow
121
- Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
122
- exit 0 # never fail the caller's install over capture
123
- }
124
-
125
- Write-Host "collector: running (pid $($proc.Id), 127.0.0.1:$Port -> $MailboxUrl)"
126
- Write-Host ""
127
- # The preload MUST be a file:// URL with forward slashes: on Windows, Node
128
- # parses a bare `--import=C:\...` as a URL whose scheme is `c:` and the app
129
- # CRASHES AT BOOT with ERR_UNSUPPORTED_ESM_URL_SCHEME. Proven live on this
130
- # machine during the CF18 host-path gate - this line is why the guidance
131
- # below is not simply $RegisterMjs.
132
- $RegisterUrl = "file:///" + ($RegisterMjs -replace "\\", "/")
133
- Write-Host "To capture a Node app on this machine, set on THAT app and restart it:" -ForegroundColor Cyan
134
- Write-Host " NODE_OPTIONS=--import=$RegisterUrl"
135
- Write-Host " CULPA_COLLECTOR_URL=http://127.0.0.1:$Port"
136
- Write-Host "(containerized app, or 2+ machines? run: culpa connect --machines <N>)"
137
- exit 0
1
+ # CF18 (D-088 items 4/5) - the capture collector's lifecycle on a Windows
2
+ # host install. ONE implementation; install-culpa.ps1, launch-culpa.ps1 and
3
+ # uninstall-culpa.ps1 each make a one-line call, so the three can never drift.
4
+ #
5
+ # culpa-collector.ps1 -Start [-MailboxUrl http://127.0.0.1:4545]
6
+ # culpa-collector.ps1 -Stop
7
+ # culpa-collector.ps1 -Status
8
+ #
9
+ # WHY A HOST PROCESS AND NOT A COMPOSE SERVICE: collectord binds 127.0.0.1
10
+ # ONLY, by design (D-082 privacy boundary - raw observation material crosses
11
+ # loopback IPC and nothing else). Docker port-publishing cannot expose a
12
+ # loopback-bound process, so a containerized collector beside the server is
13
+ # unreachable by an app running on the host - the common case this installer
14
+ # serves. The native binary on the host IS the loopback the app shares.
15
+ # (Containerized apps use deploy/capture/capture-compose.yml's netns-sharing
16
+ # sidecar instead; `culpa connect` prints which applies.)
17
+ #
18
+ # The token authenticates the collector to the mailbox target. Against the
19
+ # local culpa-api it is not currently checked (capture is never gated,
20
+ # D-031 section 7), but collectord requires one at boot and a future hosted target
21
+ # does check it - so a real one is generated once and persisted beside the
22
+ # install, never a hardcoded placeholder.
23
+
24
+ param(
25
+ [switch]$Start,
26
+ [switch]$Stop,
27
+ [switch]$Status,
28
+ [string]$MailboxUrl = "http://127.0.0.1:4545",
29
+ # CodeRabbit PR#16: overridable when 4752 is taken on the host
30
+ [int]$Port = 4752
31
+ )
32
+
33
+ $ErrorActionPreference = "Stop"
34
+ $AppDir = $PSScriptRoot
35
+ $Exe = Join-Path $AppDir "culpa-collectord-win32-x64.exe"
36
+ $RegisterMjs = Join-Path $AppDir "register.mjs"
37
+ $PidFile = Join-Path $AppDir "collector.pid"
38
+ $TokenFile = Join-Path $AppDir "collector-token.txt"
39
+ $LogFile = Join-Path $AppDir "collector.log"
40
+
41
+ function Get-RunningCollectorId {
42
+ if (-not (Test-Path $PidFile)) { return $null }
43
+ $savedPid = (Get-Content $PidFile -ErrorAction SilentlyContinue | Select-Object -First 1)
44
+ # CodeRabbit PR#16: a corrupt PID file (partial write, manual edit) used to
45
+ # TERMINATE the script - Get-Process's [int] binding fails under
46
+ # ErrorActionPreference=Stop and SilentlyContinue does not cover binding
47
+ # errors. Parse defensively: garbage means "not running", never a crash.
48
+ $parsedPid = 0
49
+ if (-not [int]::TryParse("$savedPid", [ref]$parsedPid) -or $parsedPid -le 0) { return $null }
50
+ $proc = Get-Process -Id $parsedPid -ErrorAction SilentlyContinue
51
+ # PID reuse guard: only claim it is ours if the image name matches
52
+ if ($proc -and $proc.ProcessName -like "culpa-collectord*") { return $proc.Id }
53
+ return $null
54
+ }
55
+
56
+ if ($Status) {
57
+ $running = Get-RunningCollectorId
58
+ if ($running) { Write-Host "collector: running (pid $running, port $Port)" }
59
+ else { Write-Host "collector: not running" }
60
+ exit 0
61
+ }
62
+
63
+ if ($Stop) {
64
+ $running = Get-RunningCollectorId
65
+ if ($running) {
66
+ Stop-Process -Id $running -Force -ErrorAction SilentlyContinue
67
+ Write-Host "collector: stopped (pid $running)"
68
+ } else {
69
+ Write-Host "collector: was not running"
70
+ }
71
+ Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
72
+ exit 0
73
+ }
74
+
75
+ if (-not $Start) {
76
+ Write-Host "usage: culpa-collector.ps1 -Start [-MailboxUrl <url>] | -Stop | -Status"
77
+ exit 2
78
+ }
79
+
80
+ # -- Start --------------------------------------------------------------------
81
+ if (-not (Test-Path $Exe)) {
82
+ # an older zip layout without the capture plane - say so, never fail the
83
+ # caller's install; the stack itself is unaffected
84
+ Write-Host "collector: $((Split-Path $Exe -Leaf)) not present in this package - skipping capture setup" -ForegroundColor Yellow
85
+ exit 0
86
+ }
87
+
88
+ $existing = Get-RunningCollectorId
89
+ if ($existing) {
90
+ Write-Host "collector: already running (pid $existing)"
91
+ exit 0
92
+ }
93
+
94
+ if (-not (Test-Path $TokenFile)) {
95
+ # 64 hex chars from the cryptographic RNG; persisted so restarts keep the
96
+ # same credential (a hosted mailbox target checks it)
97
+ $bytes = New-Object byte[] 32
98
+ [System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes($bytes)
99
+ ($bytes | ForEach-Object { $_.ToString("x2") }) -join "" | Set-Content $TokenFile -NoNewline
100
+ }
101
+ $token = Get-Content $TokenFile -Raw
102
+
103
+ $env:CULPA_MAILBOX_URL = $MailboxUrl
104
+ $env:CULPA_MAILBOX_TOKEN = $token
105
+ $env:CULPA_COLLECTOR_PORT = "$Port"
106
+ $proc = Start-Process -FilePath $Exe -WindowStyle Hidden -PassThru `
107
+ -RedirectStandardOutput $LogFile -RedirectStandardError "$LogFile.err"
108
+ Set-Content $PidFile $proc.Id
109
+
110
+ # bounded readiness wait: collectord prints "LISTENING <port>" on stdout
111
+ $ready = $false
112
+ for ($i = 0; $i -lt 20; $i++) {
113
+ Start-Sleep -Milliseconds 250
114
+ if ((Test-Path $LogFile) -and (Select-String -Path $LogFile -Pattern "LISTENING" -Quiet)) { $ready = $true; break }
115
+ if ($proc.HasExited) { break }
116
+ }
117
+ if (-not $ready) {
118
+ $detail = if (Test-Path "$LogFile.err") { Get-Content "$LogFile.err" -Raw } else { "(no log)" }
119
+ Write-Host "collector: failed to start - capture is OFF, everything else still works." -ForegroundColor Yellow
120
+ Write-Host " $($detail.Trim())" -ForegroundColor Yellow
121
+ Remove-Item $PidFile -Force -ErrorAction SilentlyContinue
122
+ exit 0 # never fail the caller's install over capture
123
+ }
124
+
125
+ Write-Host "collector: running (pid $($proc.Id), 127.0.0.1:$Port -> $MailboxUrl)"
126
+ Write-Host ""
127
+ # The preload MUST be a file:// URL with forward slashes: on Windows, Node
128
+ # parses a bare `--import=C:\...` as a URL whose scheme is `c:` and the app
129
+ # CRASHES AT BOOT with ERR_UNSUPPORTED_ESM_URL_SCHEME. Proven live on this
130
+ # machine during the CF18 host-path gate - this line is why the guidance
131
+ # below is not simply $RegisterMjs.
132
+ $RegisterUrl = "file:///" + ($RegisterMjs -replace "\\", "/")
133
+ Write-Host "To capture a Node app on this machine, set on THAT app and restart it:" -ForegroundColor Cyan
134
+ Write-Host " NODE_OPTIONS=--import=$RegisterUrl"
135
+ Write-Host " CULPA_COLLECTOR_URL=http://127.0.0.1:$Port"
136
+ Write-Host "(containerized app, or 2+ machines? run: culpa connect --machines <N>)"
137
+ exit 0