@secrefs/node 0.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 +21 -0
- package/README.md +124 -0
- package/dist/index.cjs +804 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +581 -0
- package/dist/index.d.ts +581 -0
- package/dist/index.js +749 -0
- package/dist/index.js.map +1 -0
- package/dist/parser.cjs +79 -0
- package/dist/parser.cjs.map +1 -0
- package/dist/parser.d.cts +41 -0
- package/dist/parser.d.ts +41 -0
- package/dist/parser.js +60 -0
- package/dist/parser.js.map +1 -0
- package/dist/secrefs.cjs +876 -0
- package/dist/secrefs.cjs.map +1 -0
- package/package.json +83 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Armistice Group
|
|
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
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# @secrefs/node
|
|
2
|
+
|
|
3
|
+
Put a reference in your config instead of a secret.
|
|
4
|
+
|
|
5
|
+
```diff
|
|
6
|
+
- DB_PASSWORD=correcthorsebatterystaple
|
|
7
|
+
+ DB_PASSWORD=sec://aws/prod/db#password
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
The second line is safe to commit. SecRefs resolves it from your own vault, in
|
|
11
|
+
memory, at the moment it is used — the value never lands on disk, in shell
|
|
12
|
+
history, or in a CI log.
|
|
13
|
+
|
|
14
|
+
**Bring your own vault.** SecRefs is not a place to store secrets and never
|
|
15
|
+
holds a copy of one. Your AWS Secrets Manager, HashiCorp Vault, or Bitwarden
|
|
16
|
+
instance stays the single source of truth; this library just knows how to read
|
|
17
|
+
from it.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install @secrefs/node # or: pnpm add @secrefs/node
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Use it
|
|
26
|
+
|
|
27
|
+
### Wrap your process
|
|
28
|
+
|
|
29
|
+
The CLI expands every `sec://` value in the environment and hands the real
|
|
30
|
+
values to your program:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx secrefs run -- node server.js
|
|
34
|
+
# secrefs: resolved 2 secret reference(s): DB_PASSWORD, STRIPE_KEY
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Your app reads `process.env.DB_PASSWORD` as it always did. Nothing else changes.
|
|
38
|
+
|
|
39
|
+
### Or call it directly
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
import { secRefs } from "@secrefs/node";
|
|
43
|
+
|
|
44
|
+
// Expand everything in process.env, once, at boot.
|
|
45
|
+
await secRefs.init();
|
|
46
|
+
|
|
47
|
+
// Or resolve a single reference at the point of use.
|
|
48
|
+
const key = await secRefs.expandString("sec://vault/secret/data/stripe#key");
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Check without resolving
|
|
52
|
+
|
|
53
|
+
`check()` validates every reference it can see and **never returns a plaintext
|
|
54
|
+
value** — safe to run in CI to catch a typo'd path before it pages someone.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
const report = await secRefs.check();
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## A stable name for a value that changes
|
|
61
|
+
|
|
62
|
+
`expandString()` re-fetches by default (`cacheTtlMs` is `0`), which means a
|
|
63
|
+
rotated secret reaches a long-running process without a restart or a redeploy:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
const secRefs = new SecRefs();
|
|
67
|
+
const REF = "sec://aws/prod/db#password";
|
|
68
|
+
|
|
69
|
+
await secRefs.expandString(REF); // "live-verify-8c41f9d2"
|
|
70
|
+
// ... the secret is rotated in AWS, out of band ...
|
|
71
|
+
await secRefs.expandString(REF); // "ROTATED-3b7e01aa" - same process, same reference
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The reference is the stable thing; the value underneath it is free to move.
|
|
75
|
+
Set `cacheTtlMs` above zero to trade a bounded window of staleness for fewer
|
|
76
|
+
round trips — concurrent resolutions of the same reference are coalesced into
|
|
77
|
+
one fetch either way.
|
|
78
|
+
|
|
79
|
+
Note the difference between the two entry points: `init()` hydrates
|
|
80
|
+
`process.env` once at boot, so a rotation reaches it on the next restart.
|
|
81
|
+
`expandString()` is the use-time path, and it is the one that picks up a
|
|
82
|
+
rotation live.
|
|
83
|
+
|
|
84
|
+
## The reference format
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
sec://<provider>/<path>[#field]
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
| Part | Meaning |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `provider` | Which vault to ask — `aws`, `vault`, `bitwarden`, `local` |
|
|
93
|
+
| `path` | The secret's identifier within that vault |
|
|
94
|
+
| `field` | Optional. Extracts one key from a JSON secret |
|
|
95
|
+
|
|
96
|
+
`sec://aws/prod/db#password` reads the `password` field out of the JSON stored
|
|
97
|
+
at `prod/db`, and returns only that field.
|
|
98
|
+
|
|
99
|
+
## Providers
|
|
100
|
+
|
|
101
|
+
| Provider | Reference | Authentication |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| AWS Secrets Manager | `sec://aws/...` | The standard AWS credential chain — env vars, shared config, or an instance/IRSA role |
|
|
104
|
+
| HashiCorp Vault | `sec://vault/...` | `VAULT_ADDR` / `VAULT_TOKEN` from the environment. KV v1 and v2 |
|
|
105
|
+
| Bitwarden | `sec://bitwarden/...` | A machine account access token |
|
|
106
|
+
| Local (dev only) | `sec://local/...` | A gitignored `.secrefs.local.json`, for teammates without vault access yet |
|
|
107
|
+
|
|
108
|
+
No provider ever needs a static credential in SecRefs' own configuration.
|
|
109
|
+
|
|
110
|
+
## Missing references fail loudly
|
|
111
|
+
|
|
112
|
+
Strict mode is the default: a reference that cannot be resolved throws rather
|
|
113
|
+
than silently yielding `undefined` and letting your app boot half-configured.
|
|
114
|
+
Pass `{ strict: false }` if you'd rather leave unresolvable references in place.
|
|
115
|
+
|
|
116
|
+
Every reference resolves concurrently, and one failure never blocks the others.
|
|
117
|
+
|
|
118
|
+
## License
|
|
119
|
+
|
|
120
|
+
MIT. See [LICENSE](./LICENSE).
|
|
121
|
+
|
|
122
|
+
The client libraries are MIT permanently and unconditionally — the SecRefs
|
|
123
|
+
control plane is licensed separately. See
|
|
124
|
+
[LICENSING.md](https://github.com/Armistice-Group/secrefs/blob/main/LICENSING.md).
|