@coffre/cli 0.1.1 → 0.1.3

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.
@@ -9,7 +9,7 @@ Two processes, configured in code:
9
9
  only the server, on a Unix socket.
10
10
 
11
11
  Run them as two users that share a group, and the process facing the network
12
- never holds the KEK. For local development, `server.ts` can run the vault
12
+ never holds the vault key. For local development, `server.ts` can run the vault
13
13
  in its own process instead; see the comment there. Everything below runs
14
14
  from this directory, on Node 24 or later.
15
15
 
@@ -19,63 +19,56 @@ from this directory, on Node 24 or later.
19
19
  pnpm install
20
20
  cp server.env.example server.env
21
21
  cp vault.env.example vault.env
22
+ chmod 600 server.env vault.env
22
23
  ```
23
24
 
24
- Fill both in: `PUBLIC_URL`, a GitHub OAuth app whose callback is
25
- `<PUBLIC_URL>/auth/callback/github`, `ROOT_ADMINS`, and the keys from
25
+ Fill in `PUBLIC_URL`, a GitHub OAuth app whose callback is
26
+ `<PUBLIC_URL>/auth/callback/github`, and `ROOT_ADMINS`. Keep each env file
27
+ readable only by its process's user.
26
28
 
27
- ```sh
28
- coffre keys
29
- ```
29
+ ## 2. The database and keys
30
30
 
31
- Run it with the CLI you ran `coffre init` with, or as
32
- `npx @coffre/cli keys`. It prints three keys and the KEK's id, once, and
33
- keeps no copy. Save its output in your password manager, with the OAuth
34
- client secret, before anything else. `KEK_ID`, `KEK` and `SIGNING_KEY` go in
35
- `vault.env`, and `AUDIT_CHAIN_KEY` in `server.env`, so that the server,
36
- which faces the network, never holds what decrypts a value:
37
-
38
- - `KEK` decrypts every value. Lose it, and every value is lost.
39
- - `SIGNING_KEY` signs the vault's log entries and member rows.
40
- - `AUDIT_CHAIN_KEY` signs the server's log entries, sessions and tokens.
41
-
42
- Lose either of the last two, and the log stops verifying and everyone is
43
- locked out.
44
-
45
- ## 2. The database
46
-
47
- Use one Postgres database with three logins: its owner for migrations,
48
- `coffre_runtime` for the server, and `coffre_vault_runtime` for the vault.
49
- As an administrator, connect to the database with `psql` and create the
50
- runtime logins. `\password` prompts for each password without putting it
51
- in a SQL statement or shell history:
52
-
53
- ```sql
54
- CREATE ROLE coffre_runtime LOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
55
- CREATE ROLE coffre_vault_runtime LOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
56
- \password coffre_runtime
57
- \password coffre_vault_runtime
58
- ```
59
-
60
- Migrate as the owner, who must also be able to create and grant roles:
31
+ Make a Postgres database, then:
61
32
 
62
33
  ```sh
63
- pnpm migrate "postgres://owner:…@db.example.com:5432/coffre"
34
+ npx @coffre/cli setup
64
35
  ```
65
36
 
66
- The migration creates the `coffre_app` and `coffre_vault` group roles and
67
- grants each login only its group's rights. Only the vault writes members
68
- and grants; each login appends to the audit log only as itself. Run the
69
- migration again after every package upgrade, before starting either process.
70
-
71
- Fill `DATABASE_URL` in each env file with the same host and database, using
72
- `coffre_runtime` in `server.env` and `coffre_vault_runtime` in `vault.env`.
73
- URL-encode special characters in passwords. Neither process gets the owner's
74
- URL. Keep each env file readable only by its process's user (`chmod 600`).
37
+ Run it with the CLI you ran `coffre init` with. It asks for the database
38
+ administrator's connection string at a hidden prompt. A script can pipe it
39
+ in, or set `COFFRE_SETUP_DATABASE_URL`; never pass it as an argument. It
40
+ makes the two logins coffre runs as, `coffre_runtime` for the server and
41
+ `coffre_vault_runtime` for the vault, migrates the database, and checks that
42
+ each login holds only its rights.
43
+
44
+ Then it shows five values on a screen of their own, which leaves nothing
45
+ behind in your scrollback. Copy each with `c` into your password manager,
46
+ beside the OAuth client secret, then into its file; `w` shows where each
47
+ goes. Nothing keeps a copy. There is one key for each process, so that the
48
+ server, which faces the network, never holds what decrypts a value.
49
+
50
+ - `server.env` takes the app key, `APP_KEY`, and the app's database URL, as
51
+ `DATABASE_URL`. The app key signs the server's log entries, sessions and
52
+ tokens. Lose it, and everyone is signed out and the log stops verifying.
53
+ - `vault.env` takes the vault ID, `VAULT_KEY_ID`, the vault key, `VAULT_KEY`,
54
+ and the vault's database URL, as `DATABASE_URL`. The vault key decrypts
55
+ every value, and the vault derives from it the key it signs its records
56
+ with. Lose it, and every value is lost. The vault ID only names it.
57
+ - Both URLs are the same database, each through its process's own login.
58
+ Neither process gets the administrator's URL.
59
+
60
+ With AWS KMS instead of a key of your own, the vault also needs a
61
+ `SIGNING_KEY` ([keys](https://github.com/erwinkn/coffre/blob/main/docs/keys.md#aws-kms)).
62
+ To do the same by hand, see
63
+ [deploy.md](https://github.com/erwinkn/coffre/blob/main/docs/deploy.md#appendix-the-database-by-hand).
64
+
65
+ Run `pnpm migrate`, with the administrator's URL in `DATABASE_URL`, after
66
+ every package upgrade, before starting either process.
75
67
 
76
68
  For tests and local development only, both URLs may instead name the same
77
- absolute SQLite file, e.g. `file:/tmp/coffre-local.db`; migrate that URL once.
78
- SQLite has no database logins or separation of privileges.
69
+ absolute SQLite file, e.g. `file:/tmp/coffre-local.db`; migrate that URL once
70
+ with `pnpm migrate`, and make the keys with `npx @coffre/cli keys`. SQLite
71
+ has no database logins or separation of privileges.
79
72
 
80
73
  ## 3. Run
81
74
 
@@ -13,11 +13,11 @@
13
13
  "conformance": "coffre-conformance node"
14
14
  },
15
15
  "dependencies": {
16
- "@coffre/server": "0.1.1",
17
- "@coffre/vault": "0.1.1"
16
+ "@coffre/server": "0.1.3",
17
+ "@coffre/vault": "0.1.3"
18
18
  },
19
19
  "devDependencies": {
20
- "@coffre/conformance": "0.1.1",
20
+ "@coffre/conformance": "0.1.3",
21
21
  "@types/node": "26.1.1",
22
22
  "typescript": "5.9.3"
23
23
  }
@@ -4,7 +4,8 @@ PORT=3000
4
4
  # Where people reach coffre, through the proxy that terminates TLS in front
5
5
  # of it: an origin, no path.
6
6
  PUBLIC_URL=https://secrets.example.com
7
- # The vault uses this Postgres database through a different login.
7
+ # From `coffre setup`: the database, as the server's own login. The vault
8
+ # uses it through another.
8
9
  DATABASE_URL=postgres://coffre_runtime:CHANGE_ME@127.0.0.1:5432/coffre
9
10
  # The vault's socket, as in vault.env.
10
11
  VAULT_SOCKET=vault.sock
@@ -13,6 +14,6 @@ VAULT_SOCKET=vault.sock
13
14
  GITHUB_CLIENT_ID=
14
15
  GITHUB_CLIENT_SECRET=
15
16
 
16
- # From `coffre keys`, saved in your password manager first: signs the
17
- # server's log entries, sessions and tokens.
18
- AUDIT_CHAIN_KEY=
17
+ # From `coffre setup`, saved in your password manager first: the app key,
18
+ # which signs the server's log entries, sessions and tokens.
19
+ APP_KEY=
@@ -1,5 +1,5 @@
1
1
  // coffre's server: the API, sign-in, pages and scheduled job, in one
2
- // process. It holds no KEK: it asks the vault, a process of its own
2
+ // process. It holds no vault key: it asks the vault, a process of its own
3
3
  // (src/vault.ts), over a Unix socket. Settings come from server.env.
4
4
  import { github, serve, signin } from '@coffre/server/node';
5
5
  import { connectVault } from '@coffre/vault/node';
@@ -16,7 +16,7 @@ const server = await serve({
16
16
  database: env('DATABASE_URL'),
17
17
  vault: connectVault(env('VAULT_SOCKET')),
18
18
  // For tests or local SQLite development only, the vault in this process:
19
- // vault: await localVault({ database: env('DATABASE_URL'), kek: …, rootAdmins: […], signingKey: … }),
19
+ // vault: await localVault({ database: env('DATABASE_URL'), kek: …, rootAdmins: […] }),
20
20
  auth: signin({
21
21
  providers: [
22
22
  github({
@@ -28,7 +28,7 @@ const server = await serve({
28
28
  }),
29
29
  ],
30
30
  }),
31
- auditChainKey: env('AUDIT_CHAIN_KEY'),
31
+ auditChainKey: env('APP_KEY'),
32
32
  });
33
33
  console.log(`coffre is listening on ${server.url}`);
34
34
 
@@ -1,7 +1,7 @@
1
1
  // The vault: the keys, and the members and grants, which it keeps in the
2
2
  // server's database through a login of its own. It answers only on a Unix
3
3
  // socket, which it makes 0660: run it as its own user, sharing a group with
4
- // the server's, and nothing that faces the network can read the KEK.
4
+ // the server's, and nothing that faces the network can read the vault key.
5
5
  // Settings come from vault.env.
6
6
  import { serveVault } from '@coffre/vault/node';
7
7
 
@@ -14,11 +14,13 @@ function env(name: string): string {
14
14
  const vault = await serveVault({
15
15
  socket: env('VAULT_SOCKET'),
16
16
  database: env('DATABASE_URL'),
17
- kek: { id: env('KEK_ID'), key: env('KEK') },
18
- // After a rotation, the KEKs before it, so the data keys they wrapped
19
- // still open: previousKeks: [{ id: 'kek-1', key: env('KEK_1') }],
17
+ kek: { id: env('VAULT_KEY_ID'), key: env('VAULT_KEY') },
18
+ // After a rotation, the vault keys before it, so the data keys they wrapped
19
+ // still open and the records signed under them before it still verify:
20
+ // previousKeks: [{ id: 'vault-2026-04-01-k7q2xm', key: env('OLD_VAULT_KEY') }],
20
21
  rootAdmins: env('ROOT_ADMINS').split(',').map((email) => email.trim()),
21
- signingKey: env('SIGNING_KEY'),
22
+ // The vault derives its signing key from the vault key. With a key a key
23
+ // service holds, such as awsKms(…), it needs one of its own: signingKey: env('SIGNING_KEY').
22
24
  });
23
25
  console.log(`the vault is listening on ${vault.socket}`);
24
26
 
@@ -2,15 +2,15 @@
2
2
  # the vault's user alone.
3
3
 
4
4
  VAULT_SOCKET=vault.sock
5
- # The server's Postgres database, as the vault's own login.
5
+ # From `coffre setup`: the server's database, as the vault's own login.
6
6
  DATABASE_URL=postgres://coffre_vault_runtime:CHANGE_ME@127.0.0.1:5432/coffre
7
7
 
8
- # From `coffre keys`, saved in your password manager first.
9
- # The key-encryption key, and its name. A rotation gives the new one a new name.
10
- KEK_ID=kek-1
11
- KEK=
12
- # Signs the vault's log entries, checkpoints and member rows.
13
- SIGNING_KEY=
8
+ # From `coffre setup`, saved in your password manager first: the vault key,
9
+ # which decrypts every value, and its ID, which is not secret. A rotation
10
+ # gives the new key a new ID. The vault derives the key it signs its
11
+ # records with from it.
12
+ VAULT_KEY_ID=vault-1
13
+ VAULT_KEY=
14
14
 
15
15
  # Comma-separated emails: the first people in, whom nobody can remove.
16
16
  ROOT_ADMINS=you@example.com
@@ -17,76 +17,66 @@ Worker secrets. Everything below runs from this directory.
17
17
  - `app/wrangler.jsonc`: `PUBLIC_URL`, and `GITHUB_CLIENT_ID` from a GitHub
18
18
  OAuth app whose callback is `<PUBLIC_URL>/auth/callback/github`.
19
19
  - `vault/wrangler.jsonc`: `ROOT_ADMINS`, the emails of the first people in,
20
- and `KEK_ID`, which `coffre keys` gives you below.
20
+ and `VAULT_KEY_ID`, which `coffre setup` gives you below.
21
21
 
22
- ## 2. The database
22
+ ## 2. The database and keys
23
23
 
24
- coffre wants a Postgres database with three logins: its owner, for
25
- migrations; `coffre_runtime`, which the app runs as; and
26
- `coffre_vault_runtime`, which the vault runs as. Create the two as plain
27
- logins. As the database's administrator, connect with `psql` and run:
28
-
29
- ```sql
30
- CREATE ROLE coffre_runtime LOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
31
- CREATE ROLE coffre_vault_runtime LOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
32
- \password coffre_runtime
33
- \password coffre_vault_runtime
34
- ```
35
-
36
- Each `\password` prompts for a different generated password. The owner
37
- must be able to create and grant roles: the migration creates `coffre_app`
38
- and `coffre_vault`, and grants each login its own group. Only the vault may
39
- write members and grants, and each appends to the log only as itself.
40
- URL-encode special characters in the passwords in these URLs:
24
+ Make a Postgres database, then, from this directory:
41
25
 
42
26
  ```sh
43
- pnpm install
44
- pnpm migrate "postgres://owner:…@db.example.com:5432/coffre"
45
- pnpm exec wrangler hyperdrive create coffre --caching-disabled \
46
- --connection-string="postgres://coffre_runtime:…@db.example.com:5432/coffre"
47
- pnpm exec wrangler hyperdrive create coffre-vault --caching-disabled \
48
- --connection-string="postgres://coffre_vault_runtime:…@db.example.com:5432/coffre"
27
+ npx @coffre/cli setup
49
28
  ```
50
29
 
51
- Keep `--caching-disabled`: Hyperdrive otherwise caches reads for up to a
52
- minute, and a revoked token or a signed-out session could keep working that
53
- long. `wrangler.jsonc` cannot set it, so for a config made another way,
54
- check `caching` in `wrangler hyperdrive get <id>`.
30
+ Run it with the CLI you ran `coffre init` with. It asks for the database
31
+ administrator's connection string at a hidden prompt. A script can pipe it
32
+ in, or set `COFFRE_SETUP_DATABASE_URL`; never pass it as an argument. It
33
+ makes the two logins coffre runs as, `coffre_runtime` for the app and
34
+ `coffre_vault_runtime` for the vault, migrates the database, and checks that
35
+ each login holds only its rights.
36
+
37
+ Then it shows five values on a screen of their own, which leaves nothing
38
+ behind in your scrollback: the app key and the app's database URL, and the
39
+ vault ID, the vault key and the vault's database URL. Copy each into your
40
+ password manager with `c`, beside the GitHub client secret; `w` shows where
41
+ each one goes. Nothing keeps a copy. There is one key for each Worker, so
42
+ that the app, which faces the network, never holds what decrypts a value:
43
+
44
+ - `VAULT_KEY`, the vault key, decrypts every value, and the vault derives
45
+ from it the key it signs its records with. Lose it, and every value is
46
+ lost.
47
+ - `APP_KEY`, the app key, signs the app's log entries, sessions and tokens.
48
+ Lose it, and everyone is signed out and the log stops verifying.
49
+ - `VAULT_KEY_ID`, the vault ID, names the vault key. It is not secret.
50
+
51
+ To do the same by hand, see
52
+ [deploy.md](https://github.com/erwinkn/coffre/blob/main/docs/deploy.md#appendix-the-database-by-hand).
53
+
54
+ ## 3. Hyperdrive and secrets
55
+
56
+ Run the two `wrangler hyperdrive create` commands from setup's screen: one
57
+ config per login, each `--caching-disabled`. Hyperdrive otherwise caches
58
+ reads for up to a minute, and a revoked token or a signed-out session could
59
+ keep working that long. `wrangler.jsonc` cannot set it, so for a config made
60
+ another way, check `caching` in `wrangler hyperdrive get <id>`.
55
61
 
56
62
  Put the ids they print under `hyperdrive`, the first in
57
- `app/wrangler.jsonc` and the second in `vault/wrangler.jsonc`. Run
58
- `pnpm migrate` again after every upgrade of `@coffre/server`, before
59
- deploying it.
60
-
61
- ## 3. Keys
63
+ `app/wrangler.jsonc` and the second in `vault/wrangler.jsonc`, and
64
+ `VAULT_KEY_ID` in `vault/wrangler.jsonc`. Then set the secrets; each command
65
+ prompts for the saved value:
62
66
 
63
67
  ```sh
64
- coffre keys
65
- ```
66
-
67
- Run it with the CLI you ran `coffre init` with, or as
68
- `npx @coffre/cli keys`. It prints three keys and the KEK's id, once, and
69
- keeps no copy. Save its output in your password manager, with the GitHub
70
- client secret, before anything else. The vault gets `KEK` and `SIGNING_KEY`,
71
- and the app `AUDIT_CHAIN_KEY`, so that the app, which faces the network,
72
- never holds what decrypts a value:
73
-
74
- - `KEK` decrypts every value. Lose it, and every value is lost.
75
- - `SIGNING_KEY` signs the vault's log entries and member rows.
76
- - `AUDIT_CHAIN_KEY` signs the app's log entries, sessions and tokens.
77
-
78
- Lose either of the last two, and the log stops verifying and everyone is
79
- locked out. Put `KEK_ID` in `vault/wrangler.jsonc`, then set the secrets;
80
- each command prompts for the saved value:
81
-
82
- ```sh
83
- pnpm exec wrangler secret put KEK -c vault/wrangler.jsonc
84
- pnpm exec wrangler secret put SIGNING_KEY -c vault/wrangler.jsonc
85
- pnpm exec wrangler secret put AUDIT_CHAIN_KEY -c app/wrangler.jsonc
68
+ pnpm exec wrangler secret put VAULT_KEY -c vault/wrangler.jsonc
69
+ pnpm exec wrangler secret put APP_KEY -c app/wrangler.jsonc
86
70
  pnpm exec wrangler secret put GITHUB_CLIENT_SECRET -c app/wrangler.jsonc
87
71
  ```
88
72
 
89
- Keep older KEKs after a rotation too: what they wrapped still needs them.
73
+ Run `pnpm migrate`, with the administrator's URL in `DATABASE_URL`, after
74
+ every upgrade of `@coffre/server`, before deploying it.
75
+
76
+ Keep older vault keys after a rotation, for good: what they wrapped still
77
+ needs them, and so does what the vault signed under them before it. With AWS KMS
78
+ instead of a key of your own, the vault also needs a `SIGNING_KEY`
79
+ ([keys](https://github.com/erwinkn/coffre/blob/main/docs/keys.md#aws-kms)).
90
80
 
91
81
  ## 4. Deploy
92
82
 
@@ -12,7 +12,7 @@ type Env = {
12
12
  /** Set for GitHub Enterprise Server; github.com otherwise. */
13
13
  GITHUB_URL?: string;
14
14
  GITHUB_API_URL?: string;
15
- AUDIT_CHAIN_KEY: string;
15
+ APP_KEY: string;
16
16
  };
17
17
 
18
18
  export default coffre((env: Env) => ({
@@ -29,5 +29,5 @@ export default coffre((env: Env) => ({
29
29
  }),
30
30
  ],
31
31
  }),
32
- auditChainKey: env.AUDIT_CHAIN_KEY,
32
+ auditChainKey: env.APP_KEY,
33
33
  }));
@@ -17,11 +17,11 @@
17
17
  "GITHUB_CLIENT_ID": "replace-with-your-client-id"
18
18
  },
19
19
  "secrets": {
20
- // AUDIT_CHAIN_KEY is from `coffre keys`; the app never gets the vault's keys.
21
- "required": ["GITHUB_CLIENT_SECRET", "AUDIT_CHAIN_KEY"]
20
+ // APP_KEY is from `coffre setup`; the app never gets the vault's keys.
21
+ "required": ["GITHUB_CLIENT_SECRET", "APP_KEY"]
22
22
  },
23
- // `wrangler hyperdrive create coffre --caching-disabled --connection-string=<runtime login URL>`
24
- // prints the id. Caching must stay off, or a revoked session keeps working
23
+ // `wrangler hyperdrive create coffre --caching-disabled`, as `coffre setup`
24
+ // shows it, prints the id. Caching must stay off, or a revoked session keeps working
25
25
  // for about a minute, and this file cannot set it: see README.md. Locally,
26
26
  // CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_HYPERDRIVE stands in for
27
27
  // the config.
@@ -14,13 +14,13 @@
14
14
  "conformance": "coffre-conformance workers"
15
15
  },
16
16
  "dependencies": {
17
- "@coffre/server": "0.1.1",
18
- "@coffre/ui": "0.1.1",
19
- "@coffre/vault": "0.1.1"
17
+ "@coffre/server": "0.1.3",
18
+ "@coffre/ui": "0.1.3",
19
+ "@coffre/vault": "0.1.3"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@cloudflare/workers-types": "5.20260920.1",
23
- "@coffre/conformance": "0.1.1",
23
+ "@coffre/conformance": "0.1.3",
24
24
  "typescript": "5.9.3",
25
25
  "wrangler": "4.118.0"
26
26
  }
@@ -5,17 +5,18 @@ import { postgres, vault } from '@coffre/vault/cloudflare';
5
5
 
6
6
  type Env = {
7
7
  VAULT_HYPERDRIVE: Hyperdrive;
8
- KEK_ID: string;
9
- KEK: string;
10
- SIGNING_KEY: string;
8
+ VAULT_KEY_ID: string;
9
+ VAULT_KEY: string;
11
10
  ROOT_ADMINS: string;
12
11
  };
13
12
 
14
13
  export default vault((env: Env) => ({
15
14
  database: postgres(env.VAULT_HYPERDRIVE),
16
- kek: { id: env.KEK_ID, key: env.KEK },
17
- // After a rotation, the KEKs before it, so the data keys they wrapped
18
- // still open: previousKeks: [{ id: 'kek-2026-09', key: env.KEK_2026_09 }],
15
+ kek: { id: env.VAULT_KEY_ID, key: env.VAULT_KEY },
16
+ // After a rotation, the vault keys before it, so the data keys they wrapped
17
+ // still open and the records signed under them before it still verify:
18
+ // previousKeks: [{ id: 'vault-2026-04-01-k7q2xm', key: env.OLD_VAULT_KEY }],
19
19
  rootAdmins: env.ROOT_ADMINS.split(',').map((email) => email.trim()),
20
- signingKey: env.SIGNING_KEY,
20
+ // The vault derives its signing key from the vault key. With a key a key
21
+ // service holds, such as awsKms(…), it needs one of its own: signingKey: env.SIGNING_KEY.
21
22
  }));
@@ -11,18 +11,20 @@
11
11
  "workers_dev": false,
12
12
  "observability": { "enabled": true },
13
13
  "vars": {
14
- // Names the KEK below: from `coffre keys`. A rotation gives the new one a new id.
15
- "KEK_ID": "kek-1",
14
+ // Names the vault key below, and is not secret: from `coffre setup`. A
15
+ // rotation gives the new key a new ID.
16
+ "VAULT_KEY_ID": "vault-1",
16
17
  // Comma-separated emails: the first people in, whom nobody can remove.
17
18
  "ROOT_ADMINS": "you@example.com"
18
19
  },
19
20
  "secrets": {
20
- // From `coffre keys`: wrangler secret put KEK, then SIGNING_KEY.
21
- "required": ["KEK", "SIGNING_KEY"]
21
+ // The vault key, from `coffre setup`: wrangler secret put VAULT_KEY. The
22
+ // vault derives the key it signs its records with from it.
23
+ "required": ["VAULT_KEY"]
22
24
  },
23
25
  // The app's database, as the vault's own login: `wrangler hyperdrive
24
- // create coffre-vault --caching-disabled --connection-string=<vault login
25
- // URL>` prints the id. Its own config, not the app's: the vault writes
26
+ // create coffre-vault --caching-disabled`, as `coffre setup` shows it,
27
+ // prints the id. Its own config, not the app's: the vault writes
26
28
  // members and grants, which the app's login may only read. Locally,
27
29
  // CLOUDFLARE_HYPERDRIVE_LOCAL_CONNECTION_STRING_VAULT_HYPERDRIVE stands in.
28
30
  "hyperdrive": [{ "binding": "VAULT_HYPERDRIVE", "id": "replace-with-your-vault-hyperdrive-id" }]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coffre/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "The coffre command line: secrets in your shell, and `coffre init` for a new deployment.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -23,13 +23,16 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@types/node": "26.1.1",
26
+ "@types/pg": "8.20.0",
27
+ "pg": "8.16.3",
26
28
  "tsdown": "0.23.0",
27
29
  "typescript": "5.9.3",
28
- "@coffre/core": "0.1.1",
29
- "@coffre/client": "0.1.1"
30
+ "@coffre/client": "0.1.3",
31
+ "@coffre/core": "0.1.3",
32
+ "@coffre/db": "0.1.3"
30
33
  },
31
34
  "scripts": {
32
- "build": "tsdown && node scripts/copy-templates.ts",
35
+ "build": "tsdown && node scripts/copy-templates.ts && node scripts/copy-migrations.ts",
33
36
  "typecheck": "tsc --noEmit",
34
37
  "test": "node --conditions=coffre:source --test"
35
38
  }