sovergate 0.1.0-alpha.1 → 0.1.0-alpha.3
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 +21 -0
- package/README.md +118 -16
- package/dist/index.d.mts +8 -1
- package/dist/index.d.ts +8 -1
- package/dist/index.js +247 -89
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +247 -89
- package/dist/index.mjs.map +1 -1
- package/package.json +15 -2
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Roberto Postolovski
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,14 +1,33 @@
|
|
|
1
|
-
# sovergate
|
|
1
|
+
# sovergate
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
TypeScript / JavaScript SDK for [Sovergate](https://sovergate.com): EU AI Act
|
|
4
|
+
Article 12 audit logging for LLM calls, with PII scrubbed inside your own
|
|
5
|
+
infrastructure.
|
|
6
|
+
|
|
7
|
+
> **Early access.** The SDK is published as an alpha and the hosted ingest
|
|
8
|
+
> service is not generally available yet. APIs may change before 1.0.
|
|
9
|
+
|
|
10
|
+
## How it works
|
|
11
|
+
|
|
12
|
+
Your app keeps calling OpenAI or Anthropic directly. Sovergate does not proxy
|
|
13
|
+
or intercept the request. After a call completes, the SDK takes a copy,
|
|
14
|
+
scrubs personal data **locally**, and sends the scrubbed copy to Sovergate in
|
|
15
|
+
the background.
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Your app ─────────────────────────────► OpenAI / Anthropic
|
|
19
|
+
│
|
|
20
|
+
└──► scrub PII locally ──► Sovergate (async, fire and forget)
|
|
21
|
+
```
|
|
4
22
|
|
|
5
23
|
## Install
|
|
6
24
|
|
|
7
25
|
```bash
|
|
8
|
-
npm install sovergate
|
|
26
|
+
npm install sovergate@alpha
|
|
9
27
|
```
|
|
10
28
|
|
|
11
|
-
Requires Node.js 18+.
|
|
29
|
+
Requires Node.js 18+. Ships ESM and CommonJS builds with TypeScript types.
|
|
30
|
+
No runtime dependencies.
|
|
12
31
|
|
|
13
32
|
## Quick start
|
|
14
33
|
|
|
@@ -21,12 +40,12 @@ const openai = new OpenAI()
|
|
|
21
40
|
init({ apiKey: 'sov_prod_xxxx' })
|
|
22
41
|
instrument(openai)
|
|
23
42
|
|
|
24
|
-
// Your existing code is
|
|
43
|
+
// Your existing code is unchanged
|
|
25
44
|
const response = await openai.chat.completions.create({
|
|
26
45
|
model: 'gpt-4o',
|
|
27
46
|
messages: [{ role: 'user', content: 'Hello' }],
|
|
28
47
|
})
|
|
29
|
-
//
|
|
48
|
+
// The response is returned immediately; logging happens in the background
|
|
30
49
|
```
|
|
31
50
|
|
|
32
51
|
Anthropic works the same way:
|
|
@@ -40,26 +59,109 @@ init({ apiKey: 'sov_prod_xxxx' })
|
|
|
40
59
|
instrument(client)
|
|
41
60
|
```
|
|
42
61
|
|
|
62
|
+
### Streaming
|
|
63
|
+
|
|
64
|
+
Streamed calls are logged too: `create({ stream: true })` on both providers, plus
|
|
65
|
+
the `chat.completions.stream()` and `messages.stream()` helpers. Your app gets
|
|
66
|
+
the same stream object and every chunk unchanged as soon as it arrives; the SDK
|
|
67
|
+
keeps a copy of the text and logs it once the stream ends. If your app stops
|
|
68
|
+
reading part-way, what it had received up to that point is logged.
|
|
69
|
+
|
|
70
|
+
OpenAI only reports token counts for a stream when you ask for them:
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
client.chat.completions.create({ ..., stream: true, stream_options: { include_usage: true } })
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Without that option the record is still logged, with 0 tokens. The SDK never
|
|
77
|
+
adds the option itself, because it changes the chunks your app receives.
|
|
78
|
+
|
|
79
|
+
## Stable PII tokens (recommended)
|
|
80
|
+
|
|
81
|
+
By default, detected PII is replaced with positional placeholders
|
|
82
|
+
(`[EMAIL_REDACTED_1]`), which are not correlatable between logs. Pass a
|
|
83
|
+
`piiKey` to replace values with deterministic, irreversible HMAC-SHA256 tokens
|
|
84
|
+
instead. The same value always maps to the same token, so Sovergate can count
|
|
85
|
+
unique people, IBANs and so on without ever receiving the raw values.
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
init({ apiKey: 'sov_prod_xxxx', piiKey: process.env.SOVERGATE_PII_KEY })
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
The `piiKey` is your secret. Keep it stable, and never send it to us: it stays
|
|
92
|
+
on your infrastructure, and without it the tokens cannot be reversed. The Python
|
|
93
|
+
SDK produces the same tokens for the same key, so services in both languages
|
|
94
|
+
count a person once.
|
|
95
|
+
|
|
43
96
|
## Options
|
|
44
97
|
|
|
45
98
|
```typescript
|
|
46
99
|
init({
|
|
47
100
|
apiKey: 'sov_prod_xxxx', // required
|
|
48
|
-
baseUrl: 'https://...',
|
|
49
|
-
|
|
101
|
+
baseUrl: 'https://...', // default: https://api.sovergate.com
|
|
102
|
+
piiKey: '<your-secret>', // stable PII tokens (see above)
|
|
103
|
+
debug: true, // print SDK internals to console.debug
|
|
50
104
|
})
|
|
51
105
|
```
|
|
52
106
|
|
|
107
|
+
## What is sent to Sovergate
|
|
108
|
+
|
|
109
|
+
For each completed call, one JSON record:
|
|
110
|
+
|
|
111
|
+
| Field | Content |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `model` | Model name returned by the provider |
|
|
114
|
+
| `messages` | Your prompt messages, **after** PII scrubbing |
|
|
115
|
+
| `response` | The model's text output, **after** PII scrubbing |
|
|
116
|
+
| `prompt_tokens`, `completion_tokens` | Token counts from the provider |
|
|
117
|
+
| `latency_ms`, `timestamp` | Call duration and start time |
|
|
118
|
+
| `finish_reason` | Why the model stopped |
|
|
119
|
+
| `pii_detections` | Category and placeholder of each scrubbed item, never the original value |
|
|
120
|
+
|
|
121
|
+
Never sent: the raw prompt or response, your LLM provider API key, or request
|
|
122
|
+
headers.
|
|
123
|
+
|
|
124
|
+
### What the scrubber detects
|
|
125
|
+
|
|
126
|
+
Regex-based, applied to every text part of the prompt and response: email
|
|
127
|
+
addresses, IP addresses, IBANs, phone numbers, dates of birth, ID numbers, and
|
|
128
|
+
names that follow a title (Mr, Mrs, Ms, Dr, Prof). Other personal data, such
|
|
129
|
+
as names without a title, is **not** detected yet, so keep data minimisation in
|
|
130
|
+
mind when you build prompts. The code is in [`src/scrubber.ts`](src/scrubber.ts).
|
|
131
|
+
|
|
53
132
|
## Guarantees
|
|
54
133
|
|
|
55
|
-
- Never blocks the event loop
|
|
56
|
-
- Never
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
|
|
134
|
+
- Never blocks the event loop: logging runs via `setImmediate`
|
|
135
|
+
- Never keeps your process alive: a script or job exits normally even while
|
|
136
|
+
records are waiting to be retried
|
|
137
|
+
- Never throws: if setup fails, the SDK logs a `console.warn` and stays out of the way
|
|
138
|
+
- Leaves your client unchanged: `create()` still returns the provider SDK's own
|
|
139
|
+
object, so `.withResponse()` and `.asResponse()` keep working, and streams keep
|
|
140
|
+
their `.controller`, `.tee()` and `.toReadableStream()`
|
|
141
|
+
- 2 second timeout on every HTTP call to Sovergate
|
|
142
|
+
- If Sovergate is unreachable, records are queued in memory (up to 10,000) and
|
|
143
|
+
retried with exponential backoff
|
|
144
|
+
- A record Sovergate permanently rejects (for example after a key is revoked) is
|
|
145
|
+
dropped with a `console.warn`, so it never blocks the records behind it
|
|
61
146
|
|
|
62
147
|
## Current limitations
|
|
63
148
|
|
|
64
|
-
-
|
|
65
|
-
-
|
|
149
|
+
- Only the text of a response is logged, streamed or not; tool calls are not.
|
|
150
|
+
- The retry queue is in memory, so queued records are lost if the process exits.
|
|
151
|
+
|
|
152
|
+
## Development
|
|
153
|
+
|
|
154
|
+
```bash
|
|
155
|
+
npm ci
|
|
156
|
+
npm run typecheck
|
|
157
|
+
npm test
|
|
158
|
+
npm run build
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## Security
|
|
162
|
+
|
|
163
|
+
Please report vulnerabilities privately. See [SECURITY.md](SECURITY.md).
|
|
164
|
+
|
|
165
|
+
## License
|
|
166
|
+
|
|
167
|
+
[MIT](LICENSE)
|
package/dist/index.d.mts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
interface InitOptions {
|
|
2
2
|
apiKey: string;
|
|
3
3
|
baseUrl?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Secret used to turn detected personal data into stable, irreversible tokens.
|
|
6
|
+
* The same value always maps to the same token, so Sovergate can count unique
|
|
7
|
+
* people without holding the data. Keep it secret and stable: it never leaves
|
|
8
|
+
* your infrastructure. Without it, placeholders are numbered per record.
|
|
9
|
+
*/
|
|
10
|
+
piiKey?: string;
|
|
4
11
|
debug?: boolean;
|
|
5
12
|
}
|
|
6
|
-
declare function init({ apiKey, baseUrl, debug }: InitOptions): void;
|
|
13
|
+
declare function init({ apiKey, baseUrl, piiKey, debug }: InitOptions): void;
|
|
7
14
|
declare function instrument(client: any): void;
|
|
8
15
|
declare function shutdown(): void;
|
|
9
16
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
interface InitOptions {
|
|
2
2
|
apiKey: string;
|
|
3
3
|
baseUrl?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Secret used to turn detected personal data into stable, irreversible tokens.
|
|
6
|
+
* The same value always maps to the same token, so Sovergate can count unique
|
|
7
|
+
* people without holding the data. Keep it secret and stable: it never leaves
|
|
8
|
+
* your infrastructure. Without it, placeholders are numbered per record.
|
|
9
|
+
*/
|
|
10
|
+
piiKey?: string;
|
|
4
11
|
debug?: boolean;
|
|
5
12
|
}
|
|
6
|
-
declare function init({ apiKey, baseUrl, debug }: InitOptions): void;
|
|
13
|
+
declare function init({ apiKey, baseUrl, piiKey, debug }: InitOptions): void;
|
|
7
14
|
declare function instrument(client: any): void;
|
|
8
15
|
declare function shutdown(): void;
|
|
9
16
|
|