@suronai/sdk 0.1.20 → 0.1.22
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 +73 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @suronai/sdk
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Runtime SDK for [Suron](https://suronai.com) — a drop-in replacement for `dotenv` that gates every app boot behind a Telegram approval before secrets are decrypted into `process.env`.
|
|
4
4
|
|
|
5
5
|
## Install
|
|
6
6
|
|
|
@@ -8,9 +8,13 @@ App SDK for Suron — drop-in replacement for `dotenv`. Every app boot is gated
|
|
|
8
8
|
npm install @suronai/sdk
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
Requires Node.js 18+. Run [`suron init`](https://www.npmjs.com/package/@suronai/cli) in your project first.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
11
15
|
## Usage
|
|
12
16
|
|
|
13
|
-
Replace your `dotenv` bootstrap
|
|
17
|
+
Replace your `dotenv` bootstrap at the very top of your entry point, before any `process.env` access:
|
|
14
18
|
|
|
15
19
|
```js
|
|
16
20
|
// before
|
|
@@ -22,17 +26,39 @@ import { config } from '@suronai/sdk'
|
|
|
22
26
|
await config()
|
|
23
27
|
```
|
|
24
28
|
|
|
25
|
-
That's it.
|
|
29
|
+
That's it. When your app starts:
|
|
30
|
+
|
|
31
|
+
1. Suron sends a message to your Telegram bot with an **Approve / Deny** button
|
|
32
|
+
2. `await config()` blocks until you tap Approve
|
|
33
|
+
3. Secrets are decrypted into `process.env` — your app continues normally
|
|
34
|
+
4. If you tap Deny, or the timeout expires, the process exits with a clear message
|
|
35
|
+
|
|
36
|
+
`suron init` can patch this automatically — it detects `dotenv` in your entry point and offers to replace it interactively.
|
|
37
|
+
|
|
38
|
+
---
|
|
26
39
|
|
|
27
40
|
## Requirements
|
|
28
41
|
|
|
29
|
-
- `.suron.json` in the working directory
|
|
30
|
-
- Encrypted `.env` in the working directory
|
|
31
|
-
- No
|
|
42
|
+
- `.suron.json` in the working directory — created by `suron init`
|
|
43
|
+
- Encrypted `.env` in the working directory — created by `suron init`
|
|
44
|
+
- No extra environment variables needed — the API URL is stored in `.suron.json`
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## API
|
|
49
|
+
|
|
50
|
+
### `config(options?)`
|
|
51
|
+
|
|
52
|
+
Drop-in safe wrapper. Handles all known Suron errors with `console.error` + `process.exit(1)`. Only unexpected errors are re-thrown.
|
|
53
|
+
|
|
54
|
+
```js
|
|
55
|
+
import { config } from '@suronai/sdk'
|
|
56
|
+
await config()
|
|
57
|
+
```
|
|
32
58
|
|
|
33
|
-
|
|
59
|
+
### `vault(options?)`
|
|
34
60
|
|
|
35
|
-
|
|
61
|
+
Same as `config()` but throws on all errors, giving you full control over error handling:
|
|
36
62
|
|
|
37
63
|
```js
|
|
38
64
|
import { vault, SuronDeniedError, SuronTimeoutError, SuronConfigError, SuronAppNotFoundError } from '@suronai/sdk'
|
|
@@ -48,30 +74,58 @@ try {
|
|
|
48
74
|
}
|
|
49
75
|
```
|
|
50
76
|
|
|
51
|
-
|
|
77
|
+
### Options
|
|
52
78
|
|
|
53
|
-
Both `config()` and `vault()` accept the same options:
|
|
79
|
+
Both `config()` and `vault()` accept the same options object:
|
|
54
80
|
|
|
55
81
|
```js
|
|
56
82
|
await config({
|
|
57
|
-
configPath:
|
|
58
|
-
timeout:
|
|
59
|
-
pollInterval: 3_000,
|
|
83
|
+
configPath: '/custom/path', // dir containing .suron.json — default: process.cwd()
|
|
84
|
+
timeout: 300_000, // ms to wait for Telegram approval — default: 5 minutes
|
|
85
|
+
pollInterval: 3_000, // ms between /status polls — default: 3s
|
|
60
86
|
})
|
|
61
87
|
```
|
|
62
88
|
|
|
89
|
+
---
|
|
90
|
+
|
|
63
91
|
## Errors
|
|
64
92
|
|
|
65
|
-
| Class |
|
|
93
|
+
| Class | Thrown when |
|
|
66
94
|
|---|---|
|
|
67
|
-
| `SuronConfigError` | `.suron.json` missing
|
|
68
|
-
| `SuronAppNotFoundError` | App not registered
|
|
95
|
+
| `SuronConfigError` | `.suron.json` missing, malformed, or `SURON_API_URL` not set |
|
|
96
|
+
| `SuronAppNotFoundError` | App not registered — run `suron init` |
|
|
69
97
|
| `SuronRateLimitError` | More than 20 boot requests in 1 hour |
|
|
70
98
|
| `SuronDeniedError` | You tapped Deny in Telegram |
|
|
71
|
-
| `SuronTimeoutError` | No approval received within timeout |
|
|
99
|
+
| `SuronTimeoutError` | No approval received within the timeout |
|
|
100
|
+
|
|
101
|
+
`config()` exits the process for all errors except `SuronRateLimitError` and unknown errors, which are re-thrown. `vault()` always throws.
|
|
102
|
+
|
|
103
|
+
---
|
|
72
104
|
|
|
73
|
-
|
|
105
|
+
## How it works
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
await config()
|
|
109
|
+
└─ reads .suron.json # gets app_id and api_url
|
|
110
|
+
└─ POST /request-access # triggers Telegram approval message
|
|
111
|
+
└─ GET /status (polling) # waits for Approve / Deny tap
|
|
112
|
+
└─ POST /fetch-key # retrieves private key (single-use token)
|
|
113
|
+
└─ dotenvx.parse(.env, key) # decrypts secrets into process.env
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The private key never touches disk during runtime. It's received in memory, used to decrypt, and the reference is dropped immediately after.
|
|
117
|
+
|
|
118
|
+
---
|
|
74
119
|
|
|
75
120
|
## Security
|
|
76
121
|
|
|
77
|
-
The SDK
|
|
122
|
+
- The SDK reads only `.suron.json` for the `app_id` — no access to `~/.suron-config`
|
|
123
|
+
- The `MASTER_KEY` lives exclusively inside the Convex deployment — the SDK never sees it
|
|
124
|
+
- `/fetch-key` is single-use — the token is consumed on first retrieval
|
|
125
|
+
- `DOTENV_PUBLIC_KEY` and `DOTENV_PRIVATE_KEY` are filtered out of `process.env` after decryption
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## Related
|
|
130
|
+
|
|
131
|
+
- [`@suronai/cli`](https://www.npmjs.com/package/@suronai/cli) — the CLI for setup and key rotation
|