@coffre/db 0.1.0 → 0.1.2
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/README.md +7 -1
- package/dist/connect.d.ts +5 -0
- package/dist/connect.js +3 -2
- package/dist/hyperdrive.js +2 -1
- package/dist/log.d.ts +7 -1
- package/dist/log.js +8 -1
- package/dist/migrate.js +2 -1
- package/dist/migrations/postgres/0000_baseline.sql +10 -7
- package/dist/migrations/postgres/meta/0000_snapshot.json +1 -1
- package/dist/migrations/postgres/meta/_journal.json +1 -1
- package/dist/postgres-Bmar8y0q.js +29 -0
- package/package.json +3 -2
- package/src/baseline/postgres.sql +10 -7
- package/src/connect.ts +4 -1
- package/src/hyperdrive.ts +2 -1
- package/src/log.ts +13 -1
- package/src/migrate.ts +2 -1
- package/src/migrations/postgres/0000_baseline.sql +10 -7
- package/src/migrations/postgres/meta/0000_snapshot.json +1 -1
- package/src/migrations/postgres/meta/_journal.json +1 -1
- package/src/postgres.ts +35 -0
- package/src/verify-runtime.ts +3 -1
package/README.md
CHANGED
|
@@ -8,7 +8,13 @@ connections, Hyperdrive's included.
|
|
|
8
8
|
A deployment does not import it. `@coffre/server` runs its migrations with
|
|
9
9
|
`coffre-server migrate`. The server and vault open the same database with
|
|
10
10
|
separate logins, `coffre_runtime` and `coffre_vault_runtime`. The migrations
|
|
11
|
-
grant each its own rights; only the owner runs migrations.
|
|
11
|
+
grant each its own rights; only the owner runs migrations. The owner needs
|
|
12
|
+
`CREATEROLE` and `CREATEDB`, and `ADMIN OPTION` on existing group roles.
|
|
13
|
+
Superuser is not required.
|
|
14
|
+
|
|
15
|
+
Node connections accept `sslrootcert=system` with `sslmode=verify-full`
|
|
16
|
+
and use Node's default trusted CAs. They check both the certificate chain
|
|
17
|
+
and the database hostname.
|
|
12
18
|
|
|
13
19
|
Part of [coffre](https://github.com/erwinkn/coffre), a secrets manager you
|
|
14
20
|
deploy as a small project of your own. Its eight `@coffre/*` packages are
|
package/dist/connect.d.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { t as Database } from "./database-CWpo5aF0.js";
|
|
2
2
|
import { Engine } from "./dialect.js";
|
|
3
|
+
import { ClientConfig } from "pg";
|
|
4
|
+
//#region src/postgres.d.ts
|
|
5
|
+
/** Keep libpq's system-root shortcut from being read as a certificate filename by pg. */
|
|
6
|
+
export declare function postgresConnection(url: string): ClientConfig;
|
|
7
|
+
//#endregion
|
|
3
8
|
//#region src/connect.d.ts
|
|
4
9
|
/**
|
|
5
10
|
* Open a database from its URL, on a Node server:
|
package/dist/connect.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { createDatabase } from "./index.js";
|
|
2
2
|
import { asPostgresDatabase } from "./portable.js";
|
|
3
|
+
import { t as postgresConnection } from "./postgres-Bmar8y0q.js";
|
|
3
4
|
import pg from "pg";
|
|
4
5
|
import { resolve } from "node:path";
|
|
5
6
|
//#region src/connect.ts
|
|
@@ -16,7 +17,7 @@ import { resolve } from "node:path";
|
|
|
16
17
|
async function openDatabase(url) {
|
|
17
18
|
switch (engineOfUrl(url)) {
|
|
18
19
|
case "postgres": {
|
|
19
|
-
const pool = new pg.Pool(
|
|
20
|
+
const pool = new pg.Pool(postgresConnection(url));
|
|
20
21
|
return {
|
|
21
22
|
engine: "postgres",
|
|
22
23
|
db: createDatabase(pool),
|
|
@@ -152,4 +153,4 @@ function numbers(result) {
|
|
|
152
153
|
return result;
|
|
153
154
|
}
|
|
154
155
|
//#endregion
|
|
155
|
-
export { engineOfUrl, openDatabase };
|
|
156
|
+
export { engineOfUrl, openDatabase, postgresConnection };
|
package/dist/hyperdrive.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as postgresConnection } from "./postgres-Bmar8y0q.js";
|
|
1
2
|
import pg from "pg";
|
|
2
3
|
//#region src/hyperdrive.ts
|
|
3
4
|
/** Postgres through Hyperdrive, the one database a Worker runs on, the app's and the vault's. */
|
|
@@ -44,7 +45,7 @@ var HyperdrivePool = class {
|
|
|
44
45
|
};
|
|
45
46
|
}
|
|
46
47
|
async #connectClient() {
|
|
47
|
-
const client = new pg.Client(
|
|
48
|
+
const client = new pg.Client(postgresConnection(this.#connectionString));
|
|
48
49
|
await client.connect();
|
|
49
50
|
return client;
|
|
50
51
|
}
|
package/dist/log.d.ts
CHANGED
|
@@ -68,5 +68,11 @@ export declare function lockLogHead(tx: Transaction): Promise<{
|
|
|
68
68
|
nextSeq: bigint;
|
|
69
69
|
headHash: Buffer;
|
|
70
70
|
}>;
|
|
71
|
-
|
|
71
|
+
/**
|
|
72
|
+
* Append `entries` under `key`. `check`, when given, runs once the head is
|
|
73
|
+
* locked and before anything is written: a writer's own condition on the
|
|
74
|
+
* log as it stands, which no other append can change until this one
|
|
75
|
+
* commits. It throws to refuse.
|
|
76
|
+
*/
|
|
77
|
+
export declare function appendEntries(tx: Transaction, key: LogKey, entries: readonly NewEntry[], check?: (tx: Transaction) => Promise<void>): Promise<Appended>;
|
|
72
78
|
//#endregion
|
package/dist/log.js
CHANGED
|
@@ -60,10 +60,17 @@ async function lockLogHead(tx) {
|
|
|
60
60
|
if (head === void 0) throw new Error("audit_chain_head is missing; refusing to write an unchained entry");
|
|
61
61
|
return head;
|
|
62
62
|
}
|
|
63
|
-
|
|
63
|
+
/**
|
|
64
|
+
* Append `entries` under `key`. `check`, when given, runs once the head is
|
|
65
|
+
* locked and before anything is written: a writer's own condition on the
|
|
66
|
+
* log as it stands, which no other append can change until this one
|
|
67
|
+
* commits. It throws to refuse.
|
|
68
|
+
*/
|
|
69
|
+
async function appendEntries(tx, key, entries, check) {
|
|
64
70
|
if (entries.length === 0) throw new Error("appendEntries called with no entries");
|
|
65
71
|
const { auditChainHead, auditLog } = tablesOf(tx);
|
|
66
72
|
const head = await lockLogHead(tx);
|
|
73
|
+
await check?.(tx);
|
|
67
74
|
const [{ now }] = await tx.select({ now: clockMillis(tx) }).from(auditChainHead);
|
|
68
75
|
const [last] = await tx.select({
|
|
69
76
|
seq: auditLog.seq,
|
package/dist/migrate.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as postgresConnection } from "./postgres-Bmar8y0q.js";
|
|
1
2
|
import { engineOfUrl } from "./connect.js";
|
|
2
3
|
import { createHash } from "node:crypto";
|
|
3
4
|
import { readFile } from "node:fs/promises";
|
|
@@ -53,8 +54,8 @@ async function postgresMigrator(url) {
|
|
|
53
54
|
import("drizzle-orm/node-postgres/migrator")
|
|
54
55
|
]);
|
|
55
56
|
const pool = new pg.Pool({
|
|
57
|
+
...postgresConnection(url),
|
|
56
58
|
application_name: "coffre-migrations",
|
|
57
|
-
connectionString: url,
|
|
58
59
|
max: 1
|
|
59
60
|
});
|
|
60
61
|
const client = await pool.connect();
|
|
@@ -308,19 +308,22 @@ DECLARE
|
|
|
308
308
|
BEGIN
|
|
309
309
|
FOREACH name IN ARRAY ARRAY['coffre_app', 'coffre_vault'] LOOP
|
|
310
310
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = name) THEN
|
|
311
|
-
EXECUTE format('CREATE ROLE %I', name);
|
|
311
|
+
EXECUTE format('CREATE ROLE %I NOLOGIN INHERIT NOCREATEDB NOCREATEROLE', name);
|
|
312
|
+
ELSE
|
|
313
|
+
-- Managed owners cannot ALTER the superuser-only attributes, even to turn them off.
|
|
314
|
+
IF EXISTS (
|
|
315
|
+
SELECT 1 FROM pg_roles WHERE rolname = name
|
|
316
|
+
AND (rolsuper OR rolreplication OR rolbypassrls)
|
|
317
|
+
) THEN
|
|
318
|
+
RAISE EXCEPTION '% has unsafe role attributes: SUPERUSER, REPLICATION and BYPASSRLS must be off', name;
|
|
319
|
+
END IF;
|
|
320
|
+
EXECUTE format('ALTER ROLE %I NOLOGIN INHERIT NOCREATEDB NOCREATEROLE', name);
|
|
312
321
|
END IF;
|
|
313
322
|
END LOOP;
|
|
314
323
|
END
|
|
315
324
|
$$;
|
|
316
325
|
--> statement-breakpoint
|
|
317
326
|
|
|
318
|
-
ALTER ROLE coffre_app
|
|
319
|
-
NOLOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
320
|
-
--> statement-breakpoint
|
|
321
|
-
ALTER ROLE coffre_vault
|
|
322
|
-
NOLOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
323
|
-
--> statement-breakpoint
|
|
324
327
|
|
|
325
328
|
DO $$
|
|
326
329
|
DECLARE
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { checkServerIdentity } from "node:tls";
|
|
2
|
+
import { parseIntoClientConfig } from "pg-connection-string";
|
|
3
|
+
//#region src/postgres.ts
|
|
4
|
+
/** Keep libpq's system-root shortcut from being read as a certificate filename by pg. */
|
|
5
|
+
function postgresConnection(url) {
|
|
6
|
+
let parsed;
|
|
7
|
+
try {
|
|
8
|
+
parsed = new URL(url);
|
|
9
|
+
} catch {
|
|
10
|
+
throw new Error("invalid Postgres URL");
|
|
11
|
+
}
|
|
12
|
+
const parameters = parsed.searchParams;
|
|
13
|
+
if (parameters.getAll("sslrootcert").at(-1) !== "system") return { connectionString: url };
|
|
14
|
+
const mode = parameters.getAll("sslmode").at(-1);
|
|
15
|
+
if (mode !== void 0 && mode !== "verify-full") throw new Error("sslrootcert=system requires sslmode=verify-full");
|
|
16
|
+
parameters.delete("sslrootcert");
|
|
17
|
+
parameters.set("sslmode", "verify-full");
|
|
18
|
+
const config = parseIntoClientConfig(parsed.toString());
|
|
19
|
+
const host = config.host;
|
|
20
|
+
if (!host) throw new Error("sslrootcert=system requires a Postgres hostname");
|
|
21
|
+
config.ssl = {
|
|
22
|
+
...config.ssl,
|
|
23
|
+
rejectUnauthorized: true,
|
|
24
|
+
checkServerIdentity: (_hostname, certificate) => checkServerIdentity(host, certificate)
|
|
25
|
+
};
|
|
26
|
+
return config;
|
|
27
|
+
}
|
|
28
|
+
//#endregion
|
|
29
|
+
export { postgresConnection as t };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@coffre/db",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "coffre's database: the schema, its migrations and the connections, on Postgres or SQLite.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -73,7 +73,8 @@
|
|
|
73
73
|
"@libsql/client": "0.18.0",
|
|
74
74
|
"drizzle-orm": "0.45.2",
|
|
75
75
|
"pg": "8.16.3",
|
|
76
|
-
"
|
|
76
|
+
"pg-connection-string": "2.14.0",
|
|
77
|
+
"@coffre/core": "0.1.2"
|
|
77
78
|
},
|
|
78
79
|
"devDependencies": {
|
|
79
80
|
"@types/node": "26.1.1",
|
|
@@ -44,19 +44,22 @@ DECLARE
|
|
|
44
44
|
BEGIN
|
|
45
45
|
FOREACH name IN ARRAY ARRAY['coffre_app', 'coffre_vault'] LOOP
|
|
46
46
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = name) THEN
|
|
47
|
-
EXECUTE format('CREATE ROLE %I', name);
|
|
47
|
+
EXECUTE format('CREATE ROLE %I NOLOGIN INHERIT NOCREATEDB NOCREATEROLE', name);
|
|
48
|
+
ELSE
|
|
49
|
+
-- Managed owners cannot ALTER the superuser-only attributes, even to turn them off.
|
|
50
|
+
IF EXISTS (
|
|
51
|
+
SELECT 1 FROM pg_roles WHERE rolname = name
|
|
52
|
+
AND (rolsuper OR rolreplication OR rolbypassrls)
|
|
53
|
+
) THEN
|
|
54
|
+
RAISE EXCEPTION '% has unsafe role attributes: SUPERUSER, REPLICATION and BYPASSRLS must be off', name;
|
|
55
|
+
END IF;
|
|
56
|
+
EXECUTE format('ALTER ROLE %I NOLOGIN INHERIT NOCREATEDB NOCREATEROLE', name);
|
|
48
57
|
END IF;
|
|
49
58
|
END LOOP;
|
|
50
59
|
END
|
|
51
60
|
$$;
|
|
52
61
|
--> statement-breakpoint
|
|
53
62
|
|
|
54
|
-
ALTER ROLE coffre_app
|
|
55
|
-
NOLOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
56
|
-
--> statement-breakpoint
|
|
57
|
-
ALTER ROLE coffre_vault
|
|
58
|
-
NOLOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
59
|
-
--> statement-breakpoint
|
|
60
63
|
|
|
61
64
|
DO $$
|
|
62
65
|
DECLARE
|
package/src/connect.ts
CHANGED
|
@@ -6,6 +6,9 @@ import pg from 'pg';
|
|
|
6
6
|
import { createDatabase, type Database } from './database.ts';
|
|
7
7
|
import type { Engine } from './dialect.ts';
|
|
8
8
|
import { asPostgresDatabase } from './portable.ts';
|
|
9
|
+
import { postgresConnection } from './postgres.ts';
|
|
10
|
+
|
|
11
|
+
export { postgresConnection } from './postgres.ts';
|
|
9
12
|
|
|
10
13
|
/**
|
|
11
14
|
* Open a database from its URL, on a Node server:
|
|
@@ -20,7 +23,7 @@ import { asPostgresDatabase } from './portable.ts';
|
|
|
20
23
|
export async function openDatabase(url: string): Promise<OpenDatabase> {
|
|
21
24
|
switch (engineOfUrl(url)) {
|
|
22
25
|
case 'postgres': {
|
|
23
|
-
const pool = new pg.Pool(
|
|
26
|
+
const pool = new pg.Pool(postgresConnection(url));
|
|
24
27
|
return { engine: 'postgres', db: createDatabase(pool), close: () => pool.end() };
|
|
25
28
|
}
|
|
26
29
|
case 'sqlite': {
|
package/src/hyperdrive.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import pg from 'pg';
|
|
2
2
|
|
|
3
3
|
import type { PoolLike } from './database.ts';
|
|
4
|
+
import { postgresConnection } from './postgres.ts';
|
|
4
5
|
|
|
5
6
|
/** Postgres through a Hyperdrive binding: `postgres(env.HYPERDRIVE)`. */
|
|
6
7
|
export type PostgresDatabase = { readonly engine: 'postgres'; readonly hyperdrive: { readonly connectionString: string } };
|
|
@@ -55,7 +56,7 @@ export class HyperdrivePool implements Exclude<PoolLike, pg.Pool> {
|
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
async #connectClient(): Promise<pg.Client> {
|
|
58
|
-
const client = new pg.Client(
|
|
59
|
+
const client = new pg.Client(postgresConnection(this.#connectionString));
|
|
59
60
|
await client.connect();
|
|
60
61
|
return client;
|
|
61
62
|
}
|
package/src/log.ts
CHANGED
|
@@ -111,12 +111,24 @@ export async function lockLogHead(tx: Transaction): Promise<{ nextSeq: bigint; h
|
|
|
111
111
|
return head;
|
|
112
112
|
}
|
|
113
113
|
|
|
114
|
-
|
|
114
|
+
/**
|
|
115
|
+
* Append `entries` under `key`. `check`, when given, runs once the head is
|
|
116
|
+
* locked and before anything is written: a writer's own condition on the
|
|
117
|
+
* log as it stands, which no other append can change until this one
|
|
118
|
+
* commits. It throws to refuse.
|
|
119
|
+
*/
|
|
120
|
+
export async function appendEntries(
|
|
121
|
+
tx: Transaction,
|
|
122
|
+
key: LogKey,
|
|
123
|
+
entries: readonly NewEntry[],
|
|
124
|
+
check?: (tx: Transaction) => Promise<void>,
|
|
125
|
+
): Promise<Appended> {
|
|
115
126
|
if (entries.length === 0) throw new Error('appendEntries called with no entries');
|
|
116
127
|
const { auditChainHead, auditLog } = tablesOf(tx);
|
|
117
128
|
|
|
118
129
|
// Every append queues here, if its transaction has not already.
|
|
119
130
|
const head = await lockLogHead(tx);
|
|
131
|
+
await check?.(tx);
|
|
120
132
|
const [{ now }] = await tx.select({ now: clockMillis(tx) }).from(auditChainHead);
|
|
121
133
|
const [last] = await tx
|
|
122
134
|
.select({ seq: auditLog.seq, hash: auditLog.hash })
|
package/src/migrate.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
|
|
5
5
|
import { engineOfUrl } from './connect.ts';
|
|
6
6
|
import type { Engine } from './dialect.ts';
|
|
7
|
+
import { postgresConnection } from './postgres.ts';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Bring a database up to date with its engine's migration tree:
|
|
@@ -118,7 +119,7 @@ async function postgresMigrator(url: string): Promise<Migrator> {
|
|
|
118
119
|
import('drizzle-orm/node-postgres'),
|
|
119
120
|
import('drizzle-orm/node-postgres/migrator'),
|
|
120
121
|
]);
|
|
121
|
-
const pool = new pg.Pool({ application_name: 'coffre-migrations',
|
|
122
|
+
const pool = new pg.Pool({ ...postgresConnection(url), application_name: 'coffre-migrations', max: 1 });
|
|
122
123
|
const client = await pool.connect();
|
|
123
124
|
return {
|
|
124
125
|
async applied() {
|
|
@@ -308,19 +308,22 @@ DECLARE
|
|
|
308
308
|
BEGIN
|
|
309
309
|
FOREACH name IN ARRAY ARRAY['coffre_app', 'coffre_vault'] LOOP
|
|
310
310
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = name) THEN
|
|
311
|
-
EXECUTE format('CREATE ROLE %I', name);
|
|
311
|
+
EXECUTE format('CREATE ROLE %I NOLOGIN INHERIT NOCREATEDB NOCREATEROLE', name);
|
|
312
|
+
ELSE
|
|
313
|
+
-- Managed owners cannot ALTER the superuser-only attributes, even to turn them off.
|
|
314
|
+
IF EXISTS (
|
|
315
|
+
SELECT 1 FROM pg_roles WHERE rolname = name
|
|
316
|
+
AND (rolsuper OR rolreplication OR rolbypassrls)
|
|
317
|
+
) THEN
|
|
318
|
+
RAISE EXCEPTION '% has unsafe role attributes: SUPERUSER, REPLICATION and BYPASSRLS must be off', name;
|
|
319
|
+
END IF;
|
|
320
|
+
EXECUTE format('ALTER ROLE %I NOLOGIN INHERIT NOCREATEDB NOCREATEROLE', name);
|
|
312
321
|
END IF;
|
|
313
322
|
END LOOP;
|
|
314
323
|
END
|
|
315
324
|
$$;
|
|
316
325
|
--> statement-breakpoint
|
|
317
326
|
|
|
318
|
-
ALTER ROLE coffre_app
|
|
319
|
-
NOLOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
320
|
-
--> statement-breakpoint
|
|
321
|
-
ALTER ROLE coffre_vault
|
|
322
|
-
NOLOGIN INHERIT NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION NOBYPASSRLS;
|
|
323
|
-
--> statement-breakpoint
|
|
324
327
|
|
|
325
328
|
DO $$
|
|
326
329
|
DECLARE
|
package/src/postgres.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { checkServerIdentity } from 'node:tls';
|
|
2
|
+
|
|
3
|
+
import { parseIntoClientConfig } from 'pg-connection-string';
|
|
4
|
+
import type { ClientConfig } from 'pg';
|
|
5
|
+
|
|
6
|
+
/** Keep libpq's system-root shortcut from being read as a certificate filename by pg. */
|
|
7
|
+
export function postgresConnection(url: string): ClientConfig {
|
|
8
|
+
let parsed: URL;
|
|
9
|
+
try {
|
|
10
|
+
parsed = new URL(url);
|
|
11
|
+
} catch {
|
|
12
|
+
// A parse error must not print the URL's password.
|
|
13
|
+
throw new Error('invalid Postgres URL');
|
|
14
|
+
}
|
|
15
|
+
const parameters = parsed.searchParams;
|
|
16
|
+
if (parameters.getAll('sslrootcert').at(-1) !== 'system') return { connectionString: url };
|
|
17
|
+
const mode = parameters.getAll('sslmode').at(-1);
|
|
18
|
+
if (mode !== undefined && mode !== 'verify-full') {
|
|
19
|
+
throw new Error('sslrootcert=system requires sslmode=verify-full');
|
|
20
|
+
}
|
|
21
|
+
parameters.delete('sslrootcert');
|
|
22
|
+
parameters.set('sslmode', 'verify-full');
|
|
23
|
+
const config = parseIntoClientConfig(parsed.toString());
|
|
24
|
+
const host = config.host;
|
|
25
|
+
if (!host) throw new Error('sslrootcert=system requires a Postgres hostname');
|
|
26
|
+
// Do not pass a connectionString too: pg would replace these SSL options.
|
|
27
|
+
// With no CA override, Node uses its default trusted roots. pg omits SNI
|
|
28
|
+
// for IP addresses, so bind verification to the actual host explicitly.
|
|
29
|
+
config.ssl = {
|
|
30
|
+
...config.ssl as object,
|
|
31
|
+
rejectUnauthorized: true,
|
|
32
|
+
checkServerIdentity: (_hostname, certificate) => checkServerIdentity(host, certificate),
|
|
33
|
+
};
|
|
34
|
+
return config;
|
|
35
|
+
}
|
package/src/verify-runtime.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import assert from 'node:assert/strict';
|
|
2
2
|
import pg from 'pg';
|
|
3
3
|
|
|
4
|
+
import { postgresConnection } from './postgres.ts';
|
|
5
|
+
|
|
4
6
|
function requiredEnvironment(name: string): string {
|
|
5
7
|
const value = process.env[name]?.trim();
|
|
6
8
|
if (!value) throw new Error(`${name} is required`);
|
|
@@ -10,7 +12,7 @@ function requiredEnvironment(name: string): string {
|
|
|
10
12
|
const expectedRole = requiredEnvironment('COFFRE_RUNTIME_ROLE');
|
|
11
13
|
const pool = new pg.Pool({
|
|
12
14
|
application_name: 'coffre-runtime-verification',
|
|
13
|
-
|
|
15
|
+
...postgresConnection(requiredEnvironment('DATABASE_URL')),
|
|
14
16
|
max: 1,
|
|
15
17
|
});
|
|
16
18
|
|