super-secret 0.0.0-stage → 1.0.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.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +219 -2
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +249 -0
  5. package/dist/cli.js.map +1 -0
  6. package/dist/index.d.ts +11 -0
  7. package/dist/index.js +12 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/manifest.d.ts +65 -0
  10. package/dist/manifest.js +163 -0
  11. package/dist/manifest.js.map +1 -0
  12. package/dist/operator.d.ts +16 -0
  13. package/dist/operator.js +63 -0
  14. package/dist/operator.js.map +1 -0
  15. package/dist/pipeline.d.ts +51 -0
  16. package/dist/pipeline.js +421 -0
  17. package/dist/pipeline.js.map +1 -0
  18. package/dist/render.d.ts +25 -0
  19. package/dist/render.js +84 -0
  20. package/dist/render.js.map +1 -0
  21. package/dist/resolve.d.ts +7 -0
  22. package/dist/resolve.js +17 -0
  23. package/dist/resolve.js.map +1 -0
  24. package/dist/rotators/cloudflareToken.d.ts +13 -0
  25. package/dist/rotators/cloudflareToken.js +54 -0
  26. package/dist/rotators/cloudflareToken.js.map +1 -0
  27. package/dist/rotators/generated.d.ts +14 -0
  28. package/dist/rotators/generated.js +31 -0
  29. package/dist/rotators/generated.js.map +1 -0
  30. package/dist/rotators/index.d.ts +11 -0
  31. package/dist/rotators/index.js +28 -0
  32. package/dist/rotators/index.js.map +1 -0
  33. package/dist/rotators/manual.d.ts +20 -0
  34. package/dist/rotators/manual.js +64 -0
  35. package/dist/rotators/manual.js.map +1 -0
  36. package/dist/rotators/probes.d.ts +61 -0
  37. package/dist/rotators/probes.js +99 -0
  38. package/dist/rotators/probes.js.map +1 -0
  39. package/dist/rotators/static.d.ts +6 -0
  40. package/dist/rotators/static.js +23 -0
  41. package/dist/rotators/static.js.map +1 -0
  42. package/dist/rotators/stripe.d.ts +33 -0
  43. package/dist/rotators/stripe.js +143 -0
  44. package/dist/rotators/stripe.js.map +1 -0
  45. package/dist/state.d.ts +21 -0
  46. package/dist/state.js +28 -0
  47. package/dist/state.js.map +1 -0
  48. package/dist/store/envFile.d.ts +21 -0
  49. package/dist/store/envFile.js +86 -0
  50. package/dist/store/envFile.js.map +1 -0
  51. package/dist/store/index.d.ts +3 -0
  52. package/dist/store/index.js +4 -0
  53. package/dist/store/index.js.map +1 -0
  54. package/dist/store/memory.d.ts +3 -0
  55. package/dist/store/memory.js +16 -0
  56. package/dist/store/memory.js.map +1 -0
  57. package/dist/store/onePassword.d.ts +111 -0
  58. package/dist/store/onePassword.js +227 -0
  59. package/dist/store/onePassword.js.map +1 -0
  60. package/dist/targets/all.d.ts +4 -0
  61. package/dist/targets/all.js +5 -0
  62. package/dist/targets/all.js.map +1 -0
  63. package/dist/targets/cloudflare.d.ts +27 -0
  64. package/dist/targets/cloudflare.js +55 -0
  65. package/dist/targets/cloudflare.js.map +1 -0
  66. package/dist/targets/envFile.d.ts +20 -0
  67. package/dist/targets/envFile.js +28 -0
  68. package/dist/targets/envFile.js.map +1 -0
  69. package/dist/targets/github.d.ts +25 -0
  70. package/dist/targets/github.js +44 -0
  71. package/dist/targets/github.js.map +1 -0
  72. package/dist/targets/index.d.ts +9 -0
  73. package/dist/targets/index.js +22 -0
  74. package/dist/targets/index.js.map +1 -0
  75. package/dist/targets/railway.d.ts +53 -0
  76. package/dist/targets/railway.js +170 -0
  77. package/dist/targets/railway.js.map +1 -0
  78. package/dist/types.d.ts +115 -0
  79. package/dist/types.js +10 -0
  80. package/dist/types.js.map +1 -0
  81. package/dist/util.d.ts +41 -0
  82. package/dist/util.js +149 -0
  83. package/dist/util.js.map +1 -0
  84. package/package.json +59 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matthew Preucil
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 CHANGED
@@ -1,3 +1,220 @@
1
- # Temporary Holding Version
1
+ # super-secret
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Import, push and rotate a project's secrets with 1Password as the store.
4
+ One manifest per repository says which env vars exist, where each one is
5
+ consumed (a Railway service, a Cloudflare Worker, GitHub Actions, a local
6
+ `.env`) and how it is rotated. Dry run is the default; nothing is written
7
+ without `--apply`; values never appear in output.
8
+
9
+ ```bash
10
+ npx super-secret status # what is where, and whether it matches the store
11
+ npx super-secret import --from env:.env --apply # one-time: the current values into the vault
12
+ npx super-secret push --apply # the store's values to every target, redeploy what changed
13
+ npx super-secret plan # what a rotation would do
14
+ npx super-secret rotate worker-token --apply # provision → store → push → deploy → probe → revoke
15
+ npx super-secret verify --previous --expect-dead # the backup slot must be dead afterwards
16
+ ```
17
+
18
+ Node 22.6 or newer. No runtime dependencies; the CLIs it drives are
19
+ [`op`](https://developer.1password.com/docs/cli/), `gh` and `wrangler`, whichever the manifest uses.
20
+
21
+ ## The manifest
22
+
23
+ `super-secret.config.ts` (or `.mjs`, or `super-secret.json` for projects that are
24
+ not TypeScript) in the repository root, or anywhere with `--manifest`:
25
+
26
+ ```ts
27
+ import { defineManifest } from 'super-secret';
28
+
29
+ export default defineManifest({
30
+ store: { kind: 'op', vault: 'my-app', item: 'production', account: 'my.1password.com' },
31
+ targets: {
32
+ cloudflare: { kind: 'cloudflare', cwd: 'worker' },
33
+ github: { kind: 'github', repo: 'me/my-app' },
34
+ railway: {
35
+ kind: 'railway',
36
+ project: '${RAILWAY_PROJECT_ID}', // read from the store
37
+ environment: '${RAILWAY_ENVIRONMENT_ID}',
38
+ services: ['api', 'worker'],
39
+ token: '${RAILWAY_ACCOUNT_TOKEN}',
40
+ },
41
+ env: { kind: 'env-file', path: '.env' }, // the developer's local copy, kept in step
42
+ },
43
+ secrets: [
44
+ {
45
+ id: 'worker-token',
46
+ description: 'Shared bearer token the API checks on every worker request',
47
+ keys: ['WORKER_TOKEN'],
48
+ targets: { cloudflare: true, railway: true, env: true },
49
+ rotator: { kind: 'generated', length: 48 },
50
+ },
51
+ {
52
+ id: 'railway-account-token',
53
+ keys: ['RAILWAY_ACCOUNT_TOKEN'],
54
+ targets: { github: true, env: true },
55
+ rotator: {
56
+ kind: 'manual',
57
+ create: 'Railway → Account settings → Tokens → Create token',
58
+ retire: 'Railway → Account settings → Tokens → delete the previous token',
59
+ probe: { kind: 'railway-account' },
60
+ },
61
+ },
62
+ {
63
+ id: 'stripe',
64
+ keys: ['STRIPE_SECRET_KEY', 'STRIPE_WEBHOOK_SECRET'],
65
+ targets: { cloudflare: true },
66
+ rotator: { kind: 'stripe-webhook-secret', url: 'https://api.example.com/stripe/webhook' },
67
+ },
68
+ ],
69
+ });
70
+ ```
71
+
72
+ A secret is a set of env-var names (`keys`) with one rotator and a map of the
73
+ targets that receive them. `true` keeps the names; `{ STORE_KEY: 'TARGET_KEY' }`
74
+ renames on the way (the same token called `RAILWAY_USAGE_TOKEN` by the app and
75
+ `RAILWAY_ACCOUNT_TOKEN` by CI).
76
+
77
+ Relative paths (`cwd`, `path`, `stateDir`) resolve against the manifest's directory, or against `root` when set (`root: '..'` for a manifest kept in `infra/`).
78
+
79
+ Config strings may read `${KEY}` from the store or the operator env, so IDs
80
+ and tokens live in the vault, not in the manifest.
81
+
82
+ ### Rotator kinds
83
+
84
+ | kind | provision | revoke |
85
+ |---|---|---|
86
+ | `generated` | a random value (`length`, `alphabet`: alnum, hex, base64url) | nothing: the old value dies when every consumer has the new one |
87
+ | `static` | never: identifiers, usernames, public DSNs | |
88
+ | `manual` | the operator mints it where `create` says and pastes it (hidden, or on stdin); checked against `pattern` and `probe` | `retire` is queued as a manual step |
89
+ | `stripe-secret-key` | manual roll in the Dashboard, paste; checked against the same account and mode | manual expire |
90
+ | `stripe-webhook-secret` | a twin endpoint at `url`; its secret ships | the old endpoint is deleted |
91
+ | `cloudflare-api-token` | the token rolls itself in place (needs "API Tokens: Edit") | none |
92
+
93
+ Probes (`probe` on `generated` and `manual`): `{ kind: 'http', url, headers, bearer, basic, expect }`,
94
+ or a preset: `railway-account`, `railway-project`, `github-token`, `stripe-key`,
95
+ `anthropic`, `openai`, `openrouter`, `sentry`, `resend`, `synoptic`, `cloudflare-token`.
96
+
97
+ A TypeScript manifest may pass a `Rotator` or `Target` object instead of a spec for anything
98
+ provider-specific (see `src/types.ts`).
99
+
100
+ ### Targets
101
+
102
+ | kind | writes | reads back | deploy |
103
+ |---|---|---|---|
104
+ | `railway` | GraphQL `variableCollectionUpsert` per service, `skipDeploys`; optional registry credentials (`registryCredentials: { username, password }` store keys) | values per service | `serviceInstanceRedeploy`, waits for the deployment to settle (`deploy: false` to skip) |
105
+ | `cloudflare` | `wrangler secret bulk` in `cwd` | names only | none needed |
106
+ | `github` | `gh secret set` (stdin), optional `environment` | names only | |
107
+ | `env-file` | a local env file (0600, timestamped backup) | values | |
108
+
109
+ Readable targets get only the keys that differ from the store. Write-only
110
+ targets get every bound key on `push`; `status` shows present/missing for them.
111
+
112
+ ## The store
113
+
114
+ One Secure Note per deployment target in one vault, with three sections:
115
+
116
+ | section | field | holds |
117
+ |---|---|---|
118
+ | `current` | `<KEY>` | the value in use (reference: `op://vault/item/current/KEY`) |
119
+ | `previous` | `<KEY>` | the value it replaced, the backup slot |
120
+ | `meta` | `<KEY>_rotated_at` | when `current` took over |
121
+
122
+ Every write moves the live value to `previous` first. `layout: 'flat'` uses
123
+ `KEY`, `KEY_previous`, `KEY_rotated_at` without sections instead (an existing
124
+ vault laid out that way keeps working). `store: { kind: 'env', file }` is the
125
+ bootstrap store for a project that has not moved to 1Password yet.
126
+
127
+ A second item, `operator` by default, holds what the tooling itself
128
+ authenticates with (a Railway account token, `GH_TOKEN`, `CLOUDFLARE_API_TOKEN`,
129
+ provider admin keys). The shell env wins; otherwise they are read from that
130
+ item, so CI needs exactly one secret, `OP_SERVICE_ACCOUNT_TOKEN`.
131
+ `import --operator NAME… --apply` fills it from the shell env.
132
+
133
+ `op` needs a session: the desktop app's CLI integration locally (set
134
+ `store.account` when several accounts are signed in), `OP_SERVICE_ACCOUNT_TOKEN`
135
+ in CI. New items are created through a 0600 JSON template so values stay off
136
+ argv; `op item edit` only takes assignments on argv, which is acceptable on a
137
+ single-user machine or an ephemeral runner.
138
+
139
+ ## What a rotation does
140
+
141
+ For each selected secret, in manifest order: **provision** the new value;
142
+ **queue** the old credential in `.super-secret/pending-revocations.json`
143
+ (git-ignore it) so a crash never leaves it live and forgotten; **store** it,
144
+ moving the old value to `previous`; **push** it to every bound target without
145
+ deploying. Then once: **deploy** each touched target; **probe** every new value;
146
+ **revoke** the queued credentials. A failed probe stops before revocation;
147
+ `revoke-pending --apply` drains the queue later, `--ack-manual` clears manual
148
+ steps you have done by hand.
149
+
150
+ `--no-deploy`, `--no-revoke`, `--targets a,b` and `--skip-manual` narrow a run.
151
+ Manual rotators need a terminal; without one (CI) they are skipped.
152
+
153
+ ## Hosts and pods: `render`
154
+
155
+ Projects that run on plain hosts or GPU pods keep a committed template of
156
+ references and render it where the values are needed:
157
+
158
+ ```
159
+ # secrets/prod.env.tpl
160
+ API_SECRET=op://my-app/production/current/API_SECRET
161
+ DATABASE_URL=op://my-app/production/current/DATABASE_URL
162
+ TLS_KEY_B64=op://my-app/production/current/TLS_KEY # multi-line → base64
163
+ PUBLIC_URL=https://example.com # literals pass through
164
+ ```
165
+
166
+ ```bash
167
+ npx super-secret render --template secrets/prod.env.tpl --check
168
+ npx super-secret render --template secrets/prod.env.tpl --out /run/app/prod.env # 0600, atomic
169
+ ```
170
+
171
+ ## From GitHub Actions
172
+
173
+ ```yaml
174
+ - uses: 1password/install-cli-action@v4
175
+ - run: npx super-secret push --apply --skip-manual
176
+ env:
177
+ OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
178
+ ```
179
+
180
+ The service account needs read/write on the vault; everything else comes from
181
+ the `operator` item.
182
+
183
+ ## Rules the code keeps
184
+
185
+ - Secret values never appear in output; `redact()` prints a prefix, a length and a short hash.
186
+ - Values reach CLIs over stdin or a 0600 file, never argv (the `op item edit` assignments are the one exception).
187
+ - Read-only calls are fine in a dry run; anything that writes checks `ctx.apply` first.
188
+ - The manifest is the inventory: a key that is not in it is not managed.
189
+
190
+ ## Releasing
191
+
192
+ Releases are cut by [semantic-release](https://semantic-release.gitbook.io/) from
193
+ `main` in CI (`.github/workflows/ci.yml`), so commits follow
194
+ [Conventional Commits](https://www.conventionalcommits.org/): `feat:` bumps the
195
+ minor version, `fix:` the patch, a `BREAKING CHANGE:` footer or `feat!:` the
196
+ major; `docs:`, `ci:`, `chore:`, `refactor:` and `test:` publish nothing. The
197
+ version in `package.json` is a placeholder; the tag, the npm version and the
198
+ GitHub release notes come from the commits.
199
+
200
+ npm authenticates the workflow by [trusted publishing](https://docs.npmjs.com/trusted-publishers)
201
+ (OIDC), so no npm token is stored anywhere. Bootstrap, once:
202
+
203
+ 1. From a laptop signed in to npm (`npm login`) and GitHub (`gh auth login`),
204
+ cut the first release with the same machinery:
205
+ `GITHUB_TOKEN=$(gh auth token) npx semantic-release --no-ci`
206
+ 2. On npmjs.com → the package → Settings → Trusted publisher: GitHub Actions,
207
+ repository `randymarsh77/super-secret`, workflow `ci.yml`.
208
+ 3. Set the repository variable `NPM_TRUSTED_PUBLISHING` to `true`
209
+ (`gh variable set NPM_TRUSTED_PUBLISHING -b true`). From then on every
210
+ release-worthy push to `main` publishes from CI with provenance.
211
+
212
+ ## Lineage
213
+
214
+ Extracted from the secrets tooling in two private projects: a TypeScript
215
+ pipeline (store interface, rotators, Railway and GitHub targets, revocation
216
+ queue) and a Python one (op-backed vault items, `op://` templates rendered on
217
+ hosts, dual-password datastore rotation). Datastore rotators (MySQL `RETAIN
218
+ CURRENT PASSWORD`, Redis ACL) are the next thing to port.
219
+
220
+ MIT.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * super-secret — import, push and rotate a project's secrets with 1Password as
4
+ * the store. Dry run is the default; nothing is written without --apply.
5
+ *
6
+ * super-secret status [--probe] what is where (store vs each target), pending revocations
7
+ * super-secret init write a starter super-secret.json
8
+ * super-secret import [ids|KEYS…] [--from env:.env] [--apply]
9
+ * copy values from an env file into the store
10
+ * super-secret import --paste KEY… [--apply] paste values (hidden) into the store
11
+ * super-secret import --operator NAME… [--apply] copy operator credentials from the shell env into the operator item
12
+ * super-secret pull <target> [ids…] [--apply] copy a readable target's values into the store (one-time sync)
13
+ * super-secret push [ids…] [--targets a,b] [--no-deploy] [--force] [--apply]
14
+ * deploy the store's values to the targets, redeploy what changed
15
+ * super-secret plan [ids…] dry run of rotate
16
+ * super-secret rotate [ids…] --apply [--targets a,b] [--no-deploy] [--no-revoke] [--skip-manual]
17
+ * super-secret verify [ids…] [--previous] [--expect-dead]
18
+ * super-secret revoke-pending [--apply] [--ack-manual]
19
+ * super-secret deploy <target>… --apply
20
+ * super-secret render --template FILE (--check | --out FILE [--format env|json])
21
+ *
22
+ * --manifest PATH picks the manifest (default: super-secret.config.{ts,mts,mjs,js} or super-secret.json in the cwd).
23
+ */
24
+ import { spawnSync } from 'node:child_process';
25
+ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
26
+ import { resolve } from 'node:path';
27
+ import { parseArgs } from 'node:util';
28
+ import { createStore, findManifest, loadManifest, resolveManifest, selectSecrets } from "./manifest.js";
29
+ import { makeOperatorEnv, operatorStore } from "./operator.js";
30
+ import { deployTargets, importStore, pullFromTarget, push, revokePending, rotate, status, verify } from "./pipeline.js";
31
+ import { formatEnv, formatJson, opReader, parseTemplate, render, writePrivate } from "./render.js";
32
+ import { EnvFileStore, memoryStore } from "./store/index.js";
33
+ import { makeLogger, readHidden } from "./util.js";
34
+ const { values: flags, positionals } = parseArgs({
35
+ args: process.argv.slice(2),
36
+ allowPositionals: true,
37
+ strict: true,
38
+ options: {
39
+ manifest: { type: 'string' },
40
+ apply: { type: 'boolean', default: false },
41
+ from: { type: 'string' },
42
+ paste: { type: 'boolean', default: false },
43
+ operator: { type: 'boolean', default: false },
44
+ targets: { type: 'string' },
45
+ 'no-deploy': { type: 'boolean', default: false },
46
+ 'no-revoke': { type: 'boolean', default: false },
47
+ 'skip-manual': { type: 'boolean', default: false },
48
+ 'ack-manual': { type: 'boolean', default: false },
49
+ 'expect-dead': { type: 'boolean', default: false },
50
+ previous: { type: 'boolean', default: false },
51
+ probe: { type: 'boolean', default: false },
52
+ force: { type: 'boolean', default: false },
53
+ template: { type: 'string' },
54
+ out: { type: 'string' },
55
+ format: { type: 'string', default: 'env' },
56
+ check: { type: 'boolean', default: false },
57
+ help: { type: 'boolean', short: 'h', default: false },
58
+ },
59
+ });
60
+ const [command = 'status', ...rest] = positionals;
61
+ function usage() {
62
+ const src = readFileSync(new URL(import.meta.url), 'utf8');
63
+ const header = src.split('*/')[0].split('\n').slice(2).map((l) => l.replace(/^ \* ?/, ''));
64
+ console.log(header.join('\n').trim());
65
+ }
66
+ if (flags.help || command === 'help') {
67
+ usage();
68
+ process.exit(0);
69
+ }
70
+ if (command === 'init') {
71
+ const file = resolve(process.cwd(), 'super-secret.json');
72
+ if (existsSync(file)) {
73
+ console.error(`${file} already exists`);
74
+ process.exit(1);
75
+ }
76
+ writeFileSync(file, JSON.stringify({
77
+ $schema: 'https://github.com/randymarsh77/super-secret#manifest',
78
+ store: { kind: 'op', vault: 'my-vault', item: 'production', account: 'my.1password.com' },
79
+ targets: {
80
+ github: { kind: 'github', repo: 'owner/repo' },
81
+ },
82
+ secrets: [
83
+ {
84
+ id: 'example-token',
85
+ description: 'Replace me: a shared bearer token the app verifies itself',
86
+ keys: ['EXAMPLE_TOKEN'],
87
+ targets: { github: true },
88
+ rotator: { kind: 'generated', length: 48 },
89
+ },
90
+ ],
91
+ }, null, 2) + '\n');
92
+ console.log(`wrote ${file}; add .super-secret/ to .gitignore`);
93
+ process.exit(0);
94
+ }
95
+ // A TypeScript manifest on a Node that does not strip types by default (22.x):
96
+ // re-run ourselves with the flag so `import()` of the .ts file works.
97
+ {
98
+ const path = flags.manifest ? resolve(process.cwd(), flags.manifest) : findManifest();
99
+ const isTs = !!path && /\.(mts|ts)$/.test(path);
100
+ const features = process.features;
101
+ if (isTs && !features.typescript && !process.execArgv.includes('--experimental-strip-types')) {
102
+ const r = spawnSync(process.execPath, ['--experimental-strip-types', '--no-warnings', ...process.argv.slice(1)], { stdio: 'inherit' });
103
+ process.exit(r.status ?? 1);
104
+ }
105
+ }
106
+ const apply = flags.apply && command !== 'plan';
107
+ const log = makeLogger(!apply);
108
+ const onlyTargets = flags.targets?.split(',').map((s) => s.trim()).filter(Boolean);
109
+ function splitIdsAndKeys(tokens, defs) {
110
+ const ids = [];
111
+ const keys = [];
112
+ for (const t of tokens)
113
+ (/^[A-Z][A-Z0-9_]*$/.test(t) ? keys : ids).push(t);
114
+ const selected = selectSecrets(defs, ids);
115
+ const known = new Set(defs.flatMap((d) => d.keys));
116
+ const unknownKeys = keys.filter((k) => !known.has(k));
117
+ if (unknownKeys.length)
118
+ throw new Error(`key(s) not in the manifest: ${unknownKeys.join(', ')}`);
119
+ return { ids, keys: keys.length ? keys : selected.flatMap((d) => d.keys) };
120
+ }
121
+ try {
122
+ if (command === 'render') {
123
+ if (!flags.template)
124
+ throw new Error('render needs --template FILE');
125
+ if (!flags.check && !flags.out)
126
+ throw new Error('render needs --check or --out FILE');
127
+ const manifest = await loadManifest(flags.manifest).catch(() => undefined);
128
+ const account = manifest?.config.store.kind === 'op' ? manifest.config.store.account : undefined;
129
+ const entries = parseTemplate(readFileSync(resolve(process.cwd(), flags.template), 'utf8'), flags.template);
130
+ const values = await render(entries, opReader(account));
131
+ for (const e of entries)
132
+ console.log(` ${e.key.padEnd(28)} ok ${e.source.startsWith('op://') ? 'reference' : 'literal'}${e.key.endsWith('_B64') ? ' (base64)' : ''}`);
133
+ if (flags.check)
134
+ console.log(`== ${entries.length} keys resolve from ${flags.template}`);
135
+ else {
136
+ writePrivate(flags.out, flags.format === 'json' ? formatJson(values) : formatEnv(values));
137
+ console.log(`== wrote ${entries.length} keys to ${flags.out} (mode 0600); delete it when it has been consumed`);
138
+ }
139
+ process.exit(0);
140
+ }
141
+ const manifest = await loadManifest(flags.manifest);
142
+ const { targets, secrets } = resolveManifest(manifest.config);
143
+ const store = createStore(manifest.config.store, apply, log, manifest.root);
144
+ const operator = makeOperatorEnv(manifest.config.store, manifest.config.operator, log);
145
+ const ctx = {
146
+ store,
147
+ apply,
148
+ log,
149
+ operator,
150
+ targets,
151
+ root: manifest.root,
152
+ stateDir: resolve(manifest.root, manifest.config.stateDir ?? '.super-secret'),
153
+ };
154
+ const dryRunHint = (verb) => {
155
+ if (!apply)
156
+ log.info(`\nDry run. Re-run with --apply to ${verb}.`);
157
+ };
158
+ switch (command) {
159
+ case 'status':
160
+ await status(selectSecrets(secrets, rest), ctx, { probe: flags.probe });
161
+ break;
162
+ case 'plan':
163
+ case 'rotate':
164
+ await rotate(selectSecrets(secrets, rest), ctx, {
165
+ deploy: !flags['no-deploy'],
166
+ revoke: !flags['no-revoke'],
167
+ targets: onlyTargets,
168
+ skipManual: flags['skip-manual'],
169
+ });
170
+ if (!apply)
171
+ log.info('\nDry run. Re-run `rotate … --apply` to execute.');
172
+ break;
173
+ case 'import': {
174
+ if (flags.operator) {
175
+ const names = rest;
176
+ if (!names.length)
177
+ throw new Error('import --operator needs the variable names to copy');
178
+ const present = {};
179
+ for (const n of names) {
180
+ const v = process.env[n] ?? (flags.paste ? await readHidden(`Paste ${n} (hidden): `) : undefined);
181
+ if (v)
182
+ present[n] = v;
183
+ else
184
+ log.note(`${n}: not in the shell env, skipped (use --paste to enter it)`);
185
+ }
186
+ const to = operatorStore(manifest.config.store, manifest.config.operator, apply, log);
187
+ await importStore(memoryStore(present, 'shell env'), to, names, ctx);
188
+ dryRunHint('write the operator item');
189
+ break;
190
+ }
191
+ const { keys } = splitIdsAndKeys(rest, secrets);
192
+ if (flags.paste) {
193
+ const pasted = {};
194
+ for (const k of keys) {
195
+ const v = await readHidden(`Paste ${k} (hidden, empty to skip): `);
196
+ if (v)
197
+ pasted[k] = v;
198
+ }
199
+ await importStore(memoryStore(pasted, 'pasted values'), store, Object.keys(pasted), ctx);
200
+ }
201
+ else {
202
+ const spec = flags.from ?? 'env:.env';
203
+ const [kind, arg] = spec.includes(':') ? [spec.slice(0, spec.indexOf(':')), spec.slice(spec.indexOf(':') + 1)] : [spec, ''];
204
+ if (kind !== 'env')
205
+ throw new Error(`--from must be env:<file> (for a target, use \`pull <target>\`)`);
206
+ const from = new EnvFileStore(resolve(manifest.root, arg || '.env'), false, log);
207
+ await importStore(from, store, keys, ctx);
208
+ }
209
+ dryRunHint('write the store');
210
+ break;
211
+ }
212
+ case 'pull': {
213
+ const [target, ...ids] = rest;
214
+ if (!target)
215
+ throw new Error('pull needs a target name');
216
+ await pullFromTarget(selectSecrets(secrets, ids), target, ctx);
217
+ dryRunHint('write the store');
218
+ break;
219
+ }
220
+ case 'push':
221
+ await push(selectSecrets(secrets, rest), ctx, { deploy: !flags['no-deploy'], targets: onlyTargets, force: flags.force });
222
+ dryRunHint('push');
223
+ break;
224
+ case 'verify': {
225
+ const ok = await verify(selectSecrets(secrets, rest), ctx, flags['expect-dead'], flags.previous ? 'previous' : 'current');
226
+ process.exit(ok ? 0 : 1);
227
+ }
228
+ // eslint-disable-next-line no-fallthrough
229
+ case 'revoke-pending':
230
+ await revokePending(secrets, ctx, { ackManual: flags['ack-manual'] });
231
+ dryRunHint('revoke');
232
+ break;
233
+ case 'deploy':
234
+ if (!rest.length)
235
+ throw new Error('deploy needs target name(s)');
236
+ await deployTargets(ctx, rest);
237
+ dryRunHint('deploy');
238
+ break;
239
+ default:
240
+ console.error(`Unknown command "${command}".\n`);
241
+ usage();
242
+ process.exit(2);
243
+ }
244
+ }
245
+ catch (e) {
246
+ console.error(`\n✗ ${e.message}`);
247
+ process.exit(1);
248
+ }
249
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export * from './types.ts';
2
+ export { redact, sha, randomSecret, run, http, statusOf, probeFromStatus, makeLogger, readHidden, interpolate, HttpError } from './util.ts';
3
+ export { resolveRef } from './resolve.ts';
4
+ export * from './store/index.ts';
5
+ export * from './targets/index.ts';
6
+ export * from './rotators/index.ts';
7
+ export { defineManifest, loadManifest, findManifest, validateManifest, resolveManifest, selectSecrets, createStore, MANIFEST_NAMES, type ManifestConfig, type SecretConfig, type StoreConfig, type OperatorConfig, type LoadedManifest, type Resolved, } from './manifest.ts';
8
+ export { makeOperatorEnv, operatorStore, OPERATOR_ITEM } from './operator.ts';
9
+ export { RevocationQueue, type PendingRevocation } from './state.ts';
10
+ export * from './pipeline.ts';
11
+ export * from './render.ts';
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export * from "./types.js";
2
+ export { redact, sha, randomSecret, run, http, statusOf, probeFromStatus, makeLogger, readHidden, interpolate, HttpError } from "./util.js";
3
+ export { resolveRef } from "./resolve.js";
4
+ export * from "./store/index.js";
5
+ export * from "./targets/index.js";
6
+ export * from "./rotators/index.js";
7
+ export { defineManifest, loadManifest, findManifest, validateManifest, resolveManifest, selectSecrets, createStore, MANIFEST_NAMES, } from "./manifest.js";
8
+ export { makeOperatorEnv, operatorStore, OPERATOR_ITEM } from "./operator.js";
9
+ export { RevocationQueue } from "./state.js";
10
+ export * from "./pipeline.js";
11
+ export * from "./render.js";
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC5I,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,cAAc,kBAAkB,CAAC;AACjC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,OAAO,EACN,cAAc,EACd,YAAY,EACZ,YAAY,EACZ,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,WAAW,EACX,cAAc,GAOd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9E,OAAO,EAAE,eAAe,EAA0B,MAAM,YAAY,CAAC;AACrE,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { type RotatorSpec } from './rotators/index.ts';
2
+ import { type OpLayout } from './store/index.ts';
3
+ import { type TargetConfig } from './targets/index.ts';
4
+ import type { Logger, Rotator, SecretDef, SecretStore, Target, TargetBinding } from './types.ts';
5
+ export type StoreConfig = {
6
+ kind: 'op';
7
+ vault: string;
8
+ /** One Secure Note per deployment target, e.g. `production`. */
9
+ item: string;
10
+ /** 1Password account (sign-in address or shorthand) when several are signed in. */
11
+ account?: string;
12
+ layout?: OpLayout;
13
+ } | {
14
+ kind: 'env';
15
+ /** Relative to the manifest. */
16
+ file: string;
17
+ };
18
+ export interface OperatorConfig {
19
+ /** 1Password item in the store's vault holding operator credentials (default `operator`). */
20
+ item?: string;
21
+ layout?: OpLayout;
22
+ }
23
+ export interface SecretConfig {
24
+ id: string;
25
+ description?: string;
26
+ keys: string[];
27
+ /** target name → true (same names) or {storeKey: targetKey}. */
28
+ targets?: Record<string, TargetBinding>;
29
+ rotator: RotatorSpec | Rotator;
30
+ disruption?: string;
31
+ }
32
+ export interface ManifestConfig {
33
+ store: StoreConfig;
34
+ /** false: operator credentials come from the shell env only. */
35
+ operator?: OperatorConfig | false;
36
+ targets?: Record<string, TargetConfig | Target>;
37
+ secrets: SecretConfig[];
38
+ /** Pending revocations live here, relative to the root (default `.super-secret`). Git-ignore it. */
39
+ stateDir?: string;
40
+ /**
41
+ * The directory relative paths resolve against (targets' cwd and files,
42
+ * stateDir), relative to the manifest file. Default: the manifest's own
43
+ * directory; a manifest kept in `infra/` sets `root: '..'`.
44
+ */
45
+ root?: string;
46
+ }
47
+ /** Identity helper so a TypeScript manifest gets completion and checking. */
48
+ export declare function defineManifest(config: ManifestConfig): ManifestConfig;
49
+ export declare const MANIFEST_NAMES: string[];
50
+ export interface LoadedManifest {
51
+ config: ManifestConfig;
52
+ path: string;
53
+ /** `config.root` resolved: relative paths resolve against it. */
54
+ root: string;
55
+ }
56
+ export declare function findManifest(cwd?: string): string | undefined;
57
+ export declare function loadManifest(path?: string, cwd?: string): Promise<LoadedManifest>;
58
+ export declare function validateManifest(cfg: ManifestConfig): string[];
59
+ export declare function createStore(cfg: StoreConfig, apply: boolean, log: Logger, root: string): SecretStore;
60
+ export interface Resolved {
61
+ targets: Record<string, Target>;
62
+ secrets: SecretDef[];
63
+ }
64
+ export declare function resolveManifest(cfg: ManifestConfig): Resolved;
65
+ export declare function selectSecrets(defs: SecretDef[], ids: string[]): SecretDef[];