@absolutejs/secrets 0.4.0 → 0.5.1

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.
@@ -0,0 +1,234 @@
1
+ {
2
+ "contract": 1,
3
+ "identity": {
4
+ "accent": "#0d9488",
5
+ "category": "infrastructure",
6
+ "description": "One `createSecretBroker()` for resolving, caching, rotating, and log-scrubbing credentials. Pluggable adapters (env vars, encrypted file, in-memory, composite), sha256 fingerprints safe for logs, an audit hook on every lookup, and `redact()` / `redactStream()` that strip known secrets out of anything headed for a log sink.",
7
+ "docsUrl": "https://github.com/absolutejs/secrets",
8
+ "name": "@absolutejs/secrets",
9
+ "tagline": "Keep API keys and passwords out of your code and logs."
10
+ },
11
+ "implements": [
12
+ {
13
+ "contract": "secrets/adapter",
14
+ "factory": "envAdapter",
15
+ "from": "@absolutejs/secrets",
16
+ "settings": {
17
+ "type": "object",
18
+ "properties": {
19
+ "prefix": {
20
+ "description": "Only environment variables starting with this prefix are treated as secrets, looked up without it (prefix 'ABS_SECRET_' makes STRIPE_KEY read ABS_SECRET_STRIPE_KEY).",
21
+ "examples": [
22
+ "ABS_SECRET_"
23
+ ],
24
+ "title": "Variable prefix",
25
+ "type": "string"
26
+ }
27
+ }
28
+ },
29
+ "title": "Environment variables (simplest — reads process.env)",
30
+ "wiring": {
31
+ "code": "envAdapter(${settings})",
32
+ "imports": [
33
+ {
34
+ "from": "@absolutejs/secrets",
35
+ "names": [
36
+ "envAdapter"
37
+ ]
38
+ }
39
+ ]
40
+ }
41
+ },
42
+ {
43
+ "contract": "secrets/adapter",
44
+ "factory": "inMemoryAdapter",
45
+ "from": "@absolutejs/secrets",
46
+ "settings": {
47
+ "type": "object",
48
+ "properties": {}
49
+ },
50
+ "title": "In memory (development only — values reset on restart)",
51
+ "wiring": {
52
+ "code": "inMemoryAdapter()",
53
+ "imports": [
54
+ {
55
+ "from": "@absolutejs/secrets",
56
+ "names": [
57
+ "inMemoryAdapter"
58
+ ]
59
+ }
60
+ ]
61
+ }
62
+ },
63
+ {
64
+ "contract": "secrets/adapter",
65
+ "factory": "encryptedFileAdapter",
66
+ "from": "@absolutejs/secrets",
67
+ "requires": {
68
+ "env": [
69
+ {
70
+ "description": "Master passphrase that unlocks the encrypted secrets file. Keep it out of the repo (password manager, host env).",
71
+ "key": "SECRETS_MASTER_PASSPHRASE",
72
+ "secret": true
73
+ }
74
+ ]
75
+ },
76
+ "settings": {
77
+ "type": "object",
78
+ "required": [
79
+ "path"
80
+ ],
81
+ "properties": {
82
+ "path": {
83
+ "default": "./var/secrets.enc.json",
84
+ "description": "Where the encrypted file lives. Safe to commit to a private repo — values are AES-256-GCM encrypted; only the master passphrase unlocks them.",
85
+ "title": "Encrypted file location",
86
+ "type": "string"
87
+ }
88
+ }
89
+ },
90
+ "title": "Encrypted file (durable — unlocked by a master passphrase)",
91
+ "wiring": {
92
+ "code": "encryptedFileAdapter({ key: { passphrase: ${env.SECRETS_MASTER_PASSPHRASE} ?? '', type: 'passphrase' }, ...${settings} })",
93
+ "imports": [
94
+ {
95
+ "from": "@absolutejs/secrets",
96
+ "names": [
97
+ "encryptedFileAdapter"
98
+ ]
99
+ }
100
+ ]
101
+ }
102
+ }
103
+ ],
104
+ "settings": {
105
+ "type": "object",
106
+ "properties": {
107
+ "cacheTtlMs": {
108
+ "description": "How long a fetched secret is reused before asking the store again, in milliseconds. Default is 1 minute.",
109
+ "minimum": 0,
110
+ "title": "Secret cache lifetime",
111
+ "x-group": "caching",
112
+ "type": "number"
113
+ },
114
+ "cacheTtlOverrides": {
115
+ "description": "Per-secret cache lifetimes (milliseconds) that override the default. Use a short lifetime for high-impact keys like admin tokens.",
116
+ "title": "Per-secret cache lifetimes",
117
+ "x-group": "caching",
118
+ "type": "object",
119
+ "patternProperties": {
120
+ "^(.*)$": {
121
+ "minimum": 0,
122
+ "type": "number"
123
+ }
124
+ }
125
+ },
126
+ "redactionEncodings": {
127
+ "description": "Which forms of a secret get scrubbed from logs. Add 'base64' to also catch secrets hidden inside tokens and cookies.",
128
+ "title": "Scrubbed encodings",
129
+ "x-group": "redaction",
130
+ "type": "array",
131
+ "items": {
132
+ "anyOf": [
133
+ {
134
+ "const": "plain",
135
+ "type": "string"
136
+ },
137
+ {
138
+ "const": "base64",
139
+ "type": "string"
140
+ }
141
+ ]
142
+ }
143
+ },
144
+ "redactionMinLength": {
145
+ "description": "Secrets shorter than this are not scrubbed from logs, to avoid blanking coincidental short matches. Default 8.",
146
+ "minimum": 1,
147
+ "title": "Minimum length to scrub",
148
+ "x-group": "redaction",
149
+ "type": "integer"
150
+ }
151
+ }
152
+ },
153
+ "slots": {
154
+ "adapter": {
155
+ "configPath": "adapter",
156
+ "contract": "secrets/adapter",
157
+ "description": "Where your secret values live",
158
+ "known": [
159
+ "@absolutejs/secrets#env",
160
+ "@absolutejs/secrets#memory",
161
+ "@absolutejs/secrets#encrypted-file"
162
+ ],
163
+ "required": true
164
+ }
165
+ },
166
+ "wiring": [
167
+ {
168
+ "id": "default",
169
+ "server": {
170
+ "code": "const secrets = createSecretBroker({ adapter: ${slot.adapter}, ...${settings} });",
171
+ "imports": [
172
+ {
173
+ "from": "@absolutejs/secrets",
174
+ "names": [
175
+ "createSecretBroker"
176
+ ]
177
+ }
178
+ ],
179
+ "placement": "module-scope"
180
+ },
181
+ "title": "Create the secret broker"
182
+ }
183
+ ],
184
+ "tools": {
185
+ "check_secret": {
186
+ "annotations": {
187
+ "readOnlyHint": true
188
+ },
189
+ "description": "Check whether a named secret is configured. Reports presence and a log-safe sha256 fingerprint — never the value.",
190
+ "input": {
191
+ "type": "object",
192
+ "required": [
193
+ "name"
194
+ ],
195
+ "properties": {
196
+ "name": {
197
+ "minLength": 1,
198
+ "type": "string"
199
+ }
200
+ }
201
+ },
202
+ "kind": "runtime"
203
+ },
204
+ "redact_text": {
205
+ "annotations": {
206
+ "readOnlyHint": true
207
+ },
208
+ "description": "Preview redaction: returns the given text with every known (cached) secret replaced by [REDACTED:name]. Useful to check a log line or error message is safe to share. Only secrets the broker has already resolved are scrubbed.",
209
+ "input": {
210
+ "type": "object",
211
+ "required": [
212
+ "text"
213
+ ],
214
+ "properties": {
215
+ "text": {
216
+ "type": "string"
217
+ }
218
+ }
219
+ },
220
+ "kind": "runtime"
221
+ },
222
+ "secret_stats": {
223
+ "annotations": {
224
+ "readOnlyHint": true
225
+ },
226
+ "description": "Cumulative broker counters since the server started: resolves (hits/misses/errors), rotations, and how often redaction actually fired.",
227
+ "input": {
228
+ "type": "object",
229
+ "properties": {}
230
+ },
231
+ "kind": "runtime"
232
+ }
233
+ }
234
+ }
package/package.json CHANGED
@@ -1,17 +1,24 @@
1
1
  {
2
2
  "name": "@absolutejs/secrets",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
4
4
  "description": "Host-side secret broker for multi-tenant Bun runtimes. Pluggable adapters (env-var, in-memory, composite, encrypted-file); audit hook per resolve; safe fingerprints for logs; redact() walks known secrets out of arbitrary text before it lands in a log sink.",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/absolutejs/secrets.git"
8
8
  },
9
+ "homepage": "https://github.com/absolutejs/secrets",
10
+ "bugs": {
11
+ "url": "https://github.com/absolutejs/secrets/issues"
12
+ },
9
13
  "main": "./dist/index.js",
10
14
  "module": "./dist/index.js",
11
15
  "types": "./dist/index.d.ts",
12
16
  "type": "module",
13
17
  "license": "BSL-1.1",
14
18
  "author": "Alex Kahn",
19
+ "absolutejs": {
20
+ "manifestContract": 1
21
+ },
15
22
  "publishConfig": {
16
23
  "access": "public"
17
24
  },
@@ -26,7 +33,7 @@
26
33
  "rotation"
27
34
  ],
28
35
  "scripts": {
29
- "build": "rm -rf dist && bun build src/index.ts --outdir dist --sourcemap --target=bun && tsc --project tsconfig.build.json",
36
+ "build": "rm -rf dist && bun build src/index.ts src/manifest.ts --outdir dist --sourcemap --target=bun && tsc --project tsconfig.build.json && absolute-manifest emit",
30
37
  "test": "bun test tests/",
31
38
  "typecheck": "tsc --noEmit",
32
39
  "format": "prettier --write \"./**/*.{ts,json,md}\"",
@@ -34,7 +41,9 @@
34
41
  "release": "bun run format && bun run check:package && bun publish"
35
42
  },
36
43
  "dependencies": {
37
- "@absolutejs/telemetry": "^0.0.2"
44
+ "@absolutejs/manifest": "^0.1.0",
45
+ "@absolutejs/telemetry": "^0.0.2",
46
+ "@sinclair/typebox": "^0.34.0"
38
47
  },
39
48
  "peerDependencies": {
40
49
  "bun-types": "^1.3.14"
@@ -50,7 +59,16 @@
50
59
  "types": "./dist/index.d.ts",
51
60
  "import": "./dist/index.js",
52
61
  "default": "./dist/index.js"
53
- }
62
+ },
63
+ "./manifest": {
64
+ "types": "./dist/manifest.d.ts",
65
+ "import": "./dist/manifest.js",
66
+ "default": "./dist/manifest.js"
67
+ },
68
+ "./manifest.json": "./dist/manifest.json"
54
69
  },
55
- "files": ["dist", "README.md"]
70
+ "files": [
71
+ "dist",
72
+ "README.md"
73
+ ]
56
74
  }