@sentroy-co/client-sdk 2.6.4 → 2.9.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/AGENTS.md CHANGED
@@ -675,11 +675,147 @@ import {
675
675
  } from "@sentroy-co/client-sdk/react"
676
676
  ```
677
677
 
678
+ ## Env Vault (`@sentroy-co/client-sdk/vault` + `/vault/react`)
679
+
680
+ Sentroy Env Vault — centralized runtime env management. Bootstrap is a
681
+ single env (`SENTROY_ENV_API_KEY`); the rest of your config lives in
682
+ the dashboard at `vault.sentroy.com`. Changing a variable does NOT
683
+ require an app rebuild — the next read picks up the new value once the
684
+ in-memory cache TTL elapses (5 min default).
685
+
686
+ This module is intentionally **separate** from the main `Sentroy`
687
+ client. They use different auth namespaces:
688
+
689
+ | Surface | Token format | Scope |
690
+ |---|---|---|
691
+ | `Sentroy` (mail/storage) | `stk_...` | per-company access token |
692
+ | Env Vault | `stk_env_...` | per-(project, environment) bootstrap token |
693
+
694
+ ### Server: `getEnv()`
695
+
696
+ ```ts
697
+ import {
698
+ configureEnvClient, // optional one-shot config
699
+ getEnv, // async, undefined if missing
700
+ getEnvOrThrow, // async, throws if missing
701
+ getAllEnvs, // bulk: { KEY: value, ... }
702
+ getPublicEnvs, // bulk: only `public: true` variables
703
+ preloadEnv, // eager hydrate at process boot
704
+ refreshEnvCache, // manual invalidation hook
705
+ setEnvCacheTTL, // runtime TTL override (seconds)
706
+ } from "@sentroy-co/client-sdk/vault"
707
+
708
+ // Optional — defaults pull from process.env
709
+ configureEnvClient({
710
+ baseUrl: "https://sentroy.com", // or self-hosted Sentroy URL
711
+ apiKey: process.env.SENTROY_ENV_API_KEY, // default
712
+ ttlSeconds: 300, // 5 min
713
+ timeoutMs: 5000,
714
+ })
715
+
716
+ await preloadEnv() // optional: fail-fast if token invalid
717
+
718
+ const dbUrl = await getEnv("DATABASE_URL") // string | undefined
719
+ const turn = await getEnvOrThrow("TURNSTILE_SECRET") // string
720
+ const all = await getAllEnvs() // includes private
721
+ const pub = await getPublicEnvs() // public:true only
722
+ ```
723
+
724
+ ### React: SSR-injected provider + hook
725
+
726
+ ```tsx
727
+ // app/layout.tsx (server component)
728
+ import { getPublicEnvs } from "@sentroy-co/client-sdk/vault"
729
+ import { EnvProvider } from "@sentroy-co/client-sdk/vault/react"
730
+
731
+ export default async function RootLayout({ children }) {
732
+ const envs = await getPublicEnvs() // public:true only — never leak secrets
733
+ return (
734
+ <html>
735
+ <body>
736
+ <EnvProvider envs={envs}>{children}</EnvProvider>
737
+ </body>
738
+ </html>
739
+ )
740
+ }
741
+ ```
742
+
743
+ ```tsx
744
+ // any "use client" component
745
+ "use client"
746
+ import { useEnv, useAllEnvs, useEnvRefresh } from "@sentroy-co/client-sdk/vault/react"
747
+
748
+ function CaptchaWidget() {
749
+ const siteKey = useEnv("TURNSTILE_SITE_KEY") // string | undefined
750
+ if (!siteKey) return null
751
+ return <Turnstile siteKey={siteKey} />
752
+ }
753
+
754
+ function ConfigPanel() {
755
+ const all = useAllEnvs() // Record<string, string> — public envs only
756
+ const { refresh, loading } = useEnvRefresh()
757
+ return <button onClick={refresh} disabled={loading}>Refresh config</button>
758
+ }
759
+ ```
760
+
761
+ ### `EnvProvider` props
762
+
763
+ | Prop | Type | Default | Notes |
764
+ |---|---|---|---|
765
+ | `envs` | `Record<string, string>` | required | SSR-fetched public envs |
766
+ | `refreshUrl` | `string` | `/api/env-vault/public` | Endpoint for client polling |
767
+ | `apiKey` | `string` | `process.env.NEXT_PUBLIC_SENTROY_ENV_API_KEY` | Bearer token for browser polling |
768
+ | `refreshIntervalMs` | `number` | `300000` (5 min) | `0` to disable polling |
769
+
770
+ ### Security notes
771
+
772
+ - `useEnv()` only ever returns variables marked `public: true` in the dashboard. Server-only secrets stay server-side.
773
+ - The provider's polling is best-effort; network failures keep the previous values (fail-soft).
774
+ - The bootstrap token is per-(project, environment). A `prod` token cannot read `staging` and vice versa.
775
+ - Variable values are AES-256-GCM encrypted at rest in the Sentroy vault DB. Decryption happens server-side just before the fetch endpoint streams the response.
776
+
777
+ ### CLI (`sentroy env ...`)
778
+
779
+ The package ships a `sentroy` binary. After `npm install` (or `npm install -g`) it's available on `PATH`; `npx sentroy ...` works without a global install.
780
+
781
+ Auth is the same `SENTROY_ENV_API_KEY` used by `getEnv()` (or pass `--token=stk_env_...`). Base URL defaults to `https://sentroy.com` (override with `SENTROY_ENV_API_URL` or `--url=`). The token's (project, environment) scope is implicit — never specified on the CLI.
782
+
783
+ ```bash
784
+ # Push a local file to the vault. Without --delete-missing it's upsert-only.
785
+ # With --delete-missing it's a full sync — any vault key not in the file
786
+ # is removed (CLI prompts for confirmation interactively).
787
+ sentroy env push .env.production --delete-missing
788
+ sentroy env push .env.production --dry-run # show diff, no writes
789
+
790
+ # Diff local vs vault without writing.
791
+ sentroy env diff .env.production --delete-missing
792
+
793
+ # Pull the vault into a local file. Refuses to overwrite without --force.
794
+ sentroy env pull .env.staging --force
795
+
796
+ # List keys (or KEY=value with --values; only public-flagged with --public-only).
797
+ sentroy env list
798
+ sentroy env list --values
799
+ sentroy env list --public-only
800
+ ```
801
+
802
+ `push` requires the token to have `write` permission (toggle when generating the token in the dashboard). `pull`, `list`, and `diff` only need `read`.
803
+
804
+ The CLI parses the same `.env` flavour as the dashboard's developer mode:
805
+
806
+ - blank line resets pending description / public flag
807
+ - `# any comment` above a key becomes the variable's description
808
+ - `# @public` on its own line marks the next key as browser-readable
809
+ - `KEY="quoted with spaces"` and `KEY='single quoted'` both supported
810
+ - `export KEY=value` prefix is stripped
811
+
812
+ REST endpoint behind `push`: `POST /api/env-vault/push` with body `{ entries: [{key, value, public?, description?}], deleteMissing?: boolean }` and `Authorization: Bearer stk_env_...`. Response: `{ added, updated, unchanged, deleted, total, project, environment }`. Each insert/update/delete writes one audit log entry (checksum, no plaintext) tagged `source: "cli-push"`.
813
+
678
814
  ## Requirements
679
815
 
680
816
  - Node.js 18+ (uses native `fetch`)
681
- - React 18+ (only if you import from `/react`)
682
- - Tailwind CSS in the host app (only for React components)
817
+ - React 18+ (only if you import from `/react` or `/vault/react`)
818
+ - Tailwind CSS in the host app (only for React UI components like `<MediaManager />`)
683
819
 
684
820
  ## Raw URL — for LLM/agent context windows
685
821
 
package/README.md CHANGED
@@ -33,7 +33,8 @@
33
33
 
34
34
  - **Mail** — verified domains, mailboxes, multi-language templates, IMAP-backed inbox, transactional and bulk send, suppressions, webhooks, audience lists, deliverability logs.
35
35
  - **Storage** — isolated buckets, multipart uploads, image and media transformations, signed download URLs.
36
- - **React drop-ins** — `<MediaManager />` and `<MediaManagerTrigger />` for instant uploaders, no glue code (`@sentroy-co/client-sdk/react`).
36
+ - **Env Vault** — runtime env variable management (`@sentroy-co/client-sdk/vault`) — change a value in the dashboard, your app picks it up on the next read; no rebuild.
37
+ - **React drop-ins** — `<MediaManager />`, `<MediaManagerTrigger />` and `<EnvProvider>` / `useEnv()` (`@sentroy-co/client-sdk/react` + `@sentroy-co/client-sdk/vault/react`).
37
38
  - **One client, two backends** — point at `https://sentroy.com` for the hosted platform, or your own deployment for self-hosted. Same API, same types.
38
39
 
39
40
  ## Install
@@ -77,6 +78,48 @@ console.log(media.url) // signed URL, served from the CDN
77
78
 
78
79
  That's the smallest useful surface. Every other resource (`domains`, `mailboxes`, `templates`, `inbox`, `audience`, `webhooks`, `suppressions`, `logs`, `buckets`, `media`) follows the same `sentroy.<resource>.<verb>(...)` shape with full TypeScript types.
79
80
 
81
+ ## Env Vault
82
+
83
+ Manage your env vars in the dashboard at [vault.sentroy.com](https://vault.sentroy.com), bootstrap your deploy with one token, and read values via a typed helper — no rebuild on change.
84
+
85
+ ```ts
86
+ // server side
87
+ import { getEnv, getEnvOrThrow, preloadEnv } from "@sentroy-co/client-sdk/vault"
88
+
89
+ await preloadEnv() // optional fail-fast at boot
90
+ const dbUrl = await getEnv("DATABASE_URL")
91
+ const turnstile = await getEnvOrThrow("BETTER_AUTH_TURNSTILE_SECRET")
92
+ ```
93
+
94
+ ```tsx
95
+ // React: SSR-injected provider + hook (no FOUC)
96
+ import { getPublicEnvs } from "@sentroy-co/client-sdk/vault"
97
+ import { EnvProvider, useEnv } from "@sentroy-co/client-sdk/vault/react"
98
+
99
+ // app/layout.tsx (server)
100
+ const envs = await getPublicEnvs()
101
+ return <EnvProvider envs={envs}>{children}</EnvProvider>
102
+
103
+ // any "use client" component
104
+ const siteKey = useEnv("TURNSTILE_SITE_KEY")
105
+ ```
106
+
107
+ Bootstrap is a single env: `SENTROY_ENV_API_KEY`. Public/private split is enforced server-side — the React hook only ever sees `public: true` variables. Full reference at [docs.sentroy.com/env-vault](https://docs.sentroy.com/env-vault).
108
+
109
+ ### CLI
110
+
111
+ The package ships a `sentroy` CLI for syncing local `.env` files to the vault — useful for build pipelines and onboarding.
112
+
113
+ ```bash
114
+ # Use SENTROY_ENV_API_KEY (or pass --token=stk_env_...)
115
+ npx sentroy env push .env.production --delete-missing
116
+ npx sentroy env diff .env.production
117
+ npx sentroy env pull .env.staging --force
118
+ npx sentroy env list --values --public-only
119
+ ```
120
+
121
+ The token's (project, environment) scope is implicit. `--delete-missing` makes the push a full sync — keys not in the local file are removed from the vault. The token must have `write` permission for `push`; everything else only needs `read`.
122
+
80
123
  ## Self-hosted vs hosted
81
124
 
82
125
  The SDK is identical in both modes. Only `baseUrl` changes:
package/bin/sentroy.js ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ // Thin shim — keeps the shebang out of TypeScript-emitted files so tsc
3
+ // can still emit them as plain CommonJS modules without preserving comments.
4
+ require("../dist/cli/index.js")
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Minimal .env parser + serializer used by the CLI.
3
+ *
4
+ * Format conventions (mirrors apps/core/components/admin/env-vault-content.tsx
5
+ * developer mode):
6
+ * - blank line resets pending description/public flag
7
+ * - `# @public` on its own line marks the next variable as browser-readable
8
+ * - `# any other text` becomes the next variable's description
9
+ * - `KEY=value` (unquoted)
10
+ * - `KEY="value with spaces"` (double-quoted; supports \n, \", \\ escapes)
11
+ * - `KEY='single quotes'` (single-quoted; literal)
12
+ * - `export KEY=value` (export prefix stripped)
13
+ *
14
+ * Anything else is reported as a parse error with the offending line number.
15
+ */
16
+ export interface DotenvEntry {
17
+ key: string;
18
+ value: string;
19
+ public: boolean;
20
+ description: string | null;
21
+ }
22
+ export interface DotenvParseResult {
23
+ entries: DotenvEntry[];
24
+ errors: {
25
+ line: number;
26
+ message: string;
27
+ }[];
28
+ }
29
+ export declare function parseDotenv(text: string): DotenvParseResult;
30
+ /**
31
+ * Inverse of parseDotenv — emit a .env document that round-trips through it.
32
+ * Quotes values that contain whitespace or shell-special characters.
33
+ */
34
+ export declare function serializeDotenv(entries: DotenvEntry[]): string;
35
+ //# sourceMappingURL=dotenv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotenv.d.ts","sourceRoot":"","sources":["../../src/cli/dotenv.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,OAAO,CAAA;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,WAAW,EAAE,CAAA;IACtB,MAAM,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;CAC5C;AAID,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,CA2F3D;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,MAAM,CAkB9D"}
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ /**
3
+ * Minimal .env parser + serializer used by the CLI.
4
+ *
5
+ * Format conventions (mirrors apps/core/components/admin/env-vault-content.tsx
6
+ * developer mode):
7
+ * - blank line resets pending description/public flag
8
+ * - `# @public` on its own line marks the next variable as browser-readable
9
+ * - `# any other text` becomes the next variable's description
10
+ * - `KEY=value` (unquoted)
11
+ * - `KEY="value with spaces"` (double-quoted; supports \n, \", \\ escapes)
12
+ * - `KEY='single quotes'` (single-quoted; literal)
13
+ * - `export KEY=value` (export prefix stripped)
14
+ *
15
+ * Anything else is reported as a parse error with the offending line number.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.parseDotenv = parseDotenv;
19
+ exports.serializeDotenv = serializeDotenv;
20
+ const KEY_PATTERN = /^[A-Z_][A-Z0-9_]*$/;
21
+ function parseDotenv(text) {
22
+ const lines = text.split(/\r?\n/);
23
+ const entries = [];
24
+ const errors = [];
25
+ const seen = new Set();
26
+ let pendingDescription = [];
27
+ let pendingPublic = false;
28
+ for (let i = 0; i < lines.length; i++) {
29
+ const raw = lines[i] ?? "";
30
+ const line = raw.trim();
31
+ if (line === "") {
32
+ pendingDescription = [];
33
+ pendingPublic = false;
34
+ continue;
35
+ }
36
+ if (line.startsWith("#")) {
37
+ const body = line.slice(1).trim();
38
+ if (body === "@public") {
39
+ pendingPublic = true;
40
+ }
41
+ else if (body) {
42
+ pendingDescription.push(body);
43
+ }
44
+ continue;
45
+ }
46
+ const work = line.startsWith("export ") ? line.slice(7).trimStart() : line;
47
+ const eq = work.indexOf("=");
48
+ if (eq <= 0) {
49
+ errors.push({
50
+ line: i + 1,
51
+ message: "invalid syntax (expected KEY=value)",
52
+ });
53
+ pendingDescription = [];
54
+ pendingPublic = false;
55
+ continue;
56
+ }
57
+ const key = work.slice(0, eq).trim();
58
+ let value = work.slice(eq + 1);
59
+ if (!KEY_PATTERN.test(key)) {
60
+ errors.push({
61
+ line: i + 1,
62
+ message: "key must match [A-Z_][A-Z0-9_]*",
63
+ });
64
+ pendingDescription = [];
65
+ pendingPublic = false;
66
+ continue;
67
+ }
68
+ const trimmed = value.trim();
69
+ if ((trimmed.startsWith('"') && trimmed.endsWith('"')) ||
70
+ (trimmed.startsWith("'") && trimmed.endsWith("'"))) {
71
+ value = trimmed.slice(1, -1);
72
+ if (trimmed.startsWith('"')) {
73
+ value = value
74
+ .replace(/\\n/g, "\n")
75
+ .replace(/\\"/g, '"')
76
+ .replace(/\\\\/g, "\\");
77
+ }
78
+ }
79
+ else {
80
+ value = trimmed;
81
+ }
82
+ if (seen.has(key)) {
83
+ errors.push({ line: i + 1, message: `duplicate key ${key}` });
84
+ pendingDescription = [];
85
+ pendingPublic = false;
86
+ continue;
87
+ }
88
+ seen.add(key);
89
+ entries.push({
90
+ key,
91
+ value,
92
+ public: pendingPublic,
93
+ description: pendingDescription.length > 0 ? pendingDescription.join(" ") : null,
94
+ });
95
+ pendingDescription = [];
96
+ pendingPublic = false;
97
+ }
98
+ return { entries, errors };
99
+ }
100
+ /**
101
+ * Inverse of parseDotenv — emit a .env document that round-trips through it.
102
+ * Quotes values that contain whitespace or shell-special characters.
103
+ */
104
+ function serializeDotenv(entries) {
105
+ const blocks = [];
106
+ for (const e of entries) {
107
+ const parts = [];
108
+ if (e.description)
109
+ parts.push(`# ${e.description}`);
110
+ if (e.public)
111
+ parts.push("# @public");
112
+ const value = e.value;
113
+ const needsQuote = /[\s"'#$`\\]/.test(value) || value === "";
114
+ const escaped = needsQuote
115
+ ? `"${value
116
+ .replace(/\\/g, "\\\\")
117
+ .replace(/"/g, '\\"')
118
+ .replace(/\n/g, "\\n")}"`
119
+ : value;
120
+ parts.push(`${e.key}=${escaped}`);
121
+ blocks.push(parts.join("\n"));
122
+ }
123
+ return blocks.join("\n\n") + (blocks.length > 0 ? "\n" : "");
124
+ }
125
+ //# sourceMappingURL=dotenv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dotenv.js","sourceRoot":"","sources":["../../src/cli/dotenv.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * `sentroy env <subcommand>` — vault sync from a local .env file.
3
+ *
4
+ * The token's (project, environment) scope is implicit; the CLI never
5
+ * asks for either since it can't change them.
6
+ */
7
+ export declare function cmdPush(args: string[]): Promise<void>;
8
+ export declare function cmdPull(args: string[]): Promise<void>;
9
+ export declare function cmdList(args: string[]): Promise<void>;
10
+ export declare function cmdDiff(args: string[]): Promise<void>;
11
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/cli/env.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAgMH,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAgF3D;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB3D;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB3D;AAID,wBAAsB,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB3D"}