@suronai/sdk 0.1.21 → 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.
Files changed (2) hide show
  1. package/README.md +73 -19
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @suronai/sdk
2
2
 
3
- App SDK for Suron — drop-in replacement for `dotenv`. Every app boot is gated behind a Telegram approval before secrets are decrypted into `process.env`.
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 with two lines at the very top of your entry point, before any `process.env` access:
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. `config()` handles all errors internally — denied boots and timeouts exit the process with a clear message. Any `process.env` access after `await config()` will have the decrypted secrets available.
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 (created by `suron init`)
30
- - Encrypted `.env` in the working directory (created by `suron init`)
31
- - No `SURON_API_URL` setup needed — the URL is stored in `.suron.json` automatically
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
- ## Advanced: `vault()`
59
+ ### `vault(options?)`
34
60
 
35
- If you want to handle errors yourself instead of letting Suron exit the process, use `vault()` directly:
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
- ## Options
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: '/custom/path', // directory containing .suron.json, default: cwd
58
- timeout: 300_000, // ms to wait for approval, default: 5 minutes
59
- pollInterval: 3_000, // ms between /status polls, default: 3s
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 | When |
93
+ | Class | Thrown when |
66
94
  |---|---|
67
- | `SuronConfigError` | `.suron.json` missing or malformed, or `SURON_API_URL` not set |
68
- | `SuronAppNotFoundError` | App not registered (`suron init` not run) |
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
- `config()` handles all of the above with `console.error + process.exit(1)`. Only `SuronRateLimitError` and unknown errors are re-thrown.
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 never reads `~/.suron`. It only reads `.suron.json` for the `app_id`, and it never handles the `MASTER_KEY`that lives exclusively inside the Convex deployment.
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@suronai/sdk",
3
- "version": "0.1.21",
3
+ "version": "0.1.22",
4
4
  "description": "App SDK for Suron — await vault() to load secrets",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",