postgresai 0.17.0-dev.5 → 0.17.0-dev.6

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 CHANGED
@@ -188,12 +188,22 @@ pgai connect 'postgresql://postgres:<password>@<host>:5432/postgres'
188
188
  It signs you in if needed, creates the `postgres_ai_mon` role (with an admin URL; otherwise it
189
189
  prints the SQL), provisions monitoring in PostgresAI Cloud, runs the express checkup (the checks
190
190
  of `pgai checkup`, as `postgres_ai_mon`) while the box starts and prints its findings (in JSON:
191
- `checkup`), waits, and prints the dashboard URL. Safe to re-run; a `--clickhouse-key` given on a
191
+ `checkup`; skipped where PostgresAI keeps the role's password: no `checkup` key, no first report),
192
+ waits, and prints the dashboard URL. Safe to re-run; a `--clickhouse-key` given on a
192
193
  re-run is checked, and a rejected one is `action_required`. For ClickHouse Managed Postgres add `--clickhouse-key <key-id>:<key-secret>`
193
194
  (a Basic Service API Reader key) for CPU, memory and disk. `--self-hosted` runs the stack on this
194
195
  machine instead. When stdout is not a terminal the result is JSON with `status`, `dashboard_url`
195
196
  and `next`. Then: `pgai databases`, `pgai status <name>`, `pgai disconnect <name>`.
196
197
 
198
+ With JSON output (`--json`, or stdout not a terminal) stderr is the progress stream: one JSON
199
+ object a line, each with `event`. Besides the steps, any other text is
200
+ `{"event":"log","level":"error"|"warn"|"info"|"debug","message":...}`: an error (also a missing
201
+ argument or a bad option; an unknown option is named without its value), a warning (`warn`: a line
202
+ with `Warning:`, also after a `[F001] ` prefix), the `--debug` request log (`debug`), and with
203
+ `--self-hosted` each line of `mon local-install`
204
+ (`"source":"mon local-install"`; `info` from its stdout, `error` from its stderr; the Grafana and
205
+ VictoriaMetrics logins it prints at its end are masked: `pgai mon show-grafana-credentials` shows them).
206
+
197
207
  `pgai init` is the same for a person at a terminal: it signs in, asks for the database URL (and,
198
208
  for ClickHouse, the API key; neither is shown as typed), then runs `pgai connect`. Without a
199
209
  terminal, or with `--json`, it only points to `pgai connect`.
@@ -211,7 +221,7 @@ terminal, or with `--json`, it only points to `pgai connect`.
211
221
  | Environment | |
212
222
  |---|---|
213
223
  | `PGAI_API_KEY` | the API key, instead of signing in (agents, CI) |
214
- | `PGAI_MON_PASSWORD` | the password of `postgres_ai_mon`. For a new role it is set; for an existing role it is checked by logging in, and never changed. Without it a new role gets a generated password |
224
+ | `PGAI_MON_PASSWORD` | the password of `postgres_ai_mon`. For a new role it is set; for an existing role it is checked by logging in, and never changed. Without it a new role gets a generated password. Not needed for another database on a server PostgresAI already monitors for the organization, with `sslmode=require` or `verify-*` in the URL (see below) |
215
225
  | `PGPASSWORD` | the password for a URL without one. With a `postgres_ai_mon` URL it is the password the monitoring box gets, once the server has checked it |
216
226
  | `PGSSLMODE` | the `sslmode` for a URL without one (`sslmode` in the URL wins, as in libpq) |
217
227
  | `CLICKHOUSE_KEY_ID` + `CLICKHOUSE_KEY_SECRET` | instead of `--clickhouse-key`; read for ClickHouse hosts only |
@@ -220,9 +230,25 @@ terminal, or with `--json`, it only points to `pgai connect`.
220
230
  existing one. If the role exists and you do not have its password (a reconnect after
221
231
  `pgai disconnect`, say), `pgai connect <admin-url> --reset-password` sets a new one
222
232
  (`PGAI_MON_PASSWORD`, else generated). It is refused while another database on the same server (the same host name, in this
223
- organization) is monitored with the role, with `--self-hosted`, and for a database already
224
- connected. Anything else that logs in as `postgres_ai_mon` (another organization, another host
225
- name for the same server, a connect running at the same time) needs the new password.
233
+ organization) is monitored with the role, while a box is named `Monitoring <hash>` (the platform
234
+ could not read its URL, so its server is not known), with `--self-hosted`, and for a database
235
+ already connected. After the price is accepted, the run takes the platform's lock on the server (its host
236
+ name and port, in this organization) until the box is requested. A second `--reset-password` for
237
+ the same server exits 3 meanwhile. A run that stopped, or whose box request got no answer, frees the
238
+ server 15 minutes after it took the lock. A platform without the lock answers "set
239
+ `PGAI_MON_PASSWORD`" instead. Anything else that logs in as `postgres_ai_mon` (another organization,
240
+ another host name for the same server, a connect without `--reset-password` running at the same
241
+ time) needs the new password.
242
+
243
+ Another database on a server PostgresAI already monitors for the organization needs neither: with
244
+ `sslmode=require` or `verify-*` in the URL, the role keeps its password, the box's URL carries
245
+ none, and PostgresAI fills in the one it kept from the first `connect` (only over TLS, each query
246
+ parameter once, and only while a box on that server is not deleted, being deleted, or failed to
247
+ delete). The express checkup is skipped then: it runs only as `postgres_ai_mon`, never as the
248
+ admin. The full checkup follows on the box. On a server without TLS the kept password cannot be
249
+ used: set `PGAI_MON_PASSWORD`, or turn TLS on; if nobody has the password, disconnect the server's
250
+ other databases, then `--reset-password` with `PGAI_MON_PASSWORD` set to a new one, and connect
251
+ them again with it (`connect` names them).
226
252
 
227
253
  When the role exists (an admin URL with `PGAI_MON_PASSWORD`, or the role's own URL), `connect`
228
254
  also logs in once as `postgres_ai_mon` with a random password, to learn whether the server checks
@@ -269,6 +295,16 @@ user; the name of the connected database (`<host>[:<port>]/<database>`) uses tha
269
295
  key in its environment (`PGAI_DB_URL`, `PGAI_API_KEY`, `CLICKHOUSE_*`), not in its arguments.
270
296
  `mon local-install` reads `PGAI_DB_URL` like `--db-url`, and `PGAI_API_KEY` only together with
271
297
  `PGAI_DB_URL`: an exported `PGAI_API_KEY` alone does not change a plain or `--demo` install.
298
+ `mon targets add [name]` reads `PGAI_DB_URL` when argv has no `postgres://` / `postgresql://` URL
299
+ (a URL in argv wins); with it set, a lone argument other than a plain name (ASCII letters,
300
+ digits, `.`, `_`, `=`, `-`, with no `password=` / `pwd=`) is refused. Its default name is
301
+ `<host>-<database>`. Percent-encode the user name and the password one at a time (all but ASCII
302
+ letters, digits, `-`, `.`, `_` and `~`), and an `@` in the database name or the query. A user name
303
+ or password that pgx would misread or refuse is refused; an `@` after the host is refused, since it
304
+ cannot be told apart from one in a password; so is a control character anywhere in the URL.
305
+ Under sudo, pass `PGAI_DB_URL` on stdin, not with `--preserve-env`: sudo logs the variables it keeps.
306
+ Where sudoers enables I/O logging (`log_input`), sudo records stdin too: read the URL from a file
307
+ of mode 0600 inside the root shell instead.
272
308
 
273
309
  ### Authentication
274
310
 
@@ -385,6 +421,11 @@ When `--instance-id <uuid>` (or `PGAI_INSTANCE_ID`) is set, `local-install` forw
385
421
  ```bash
386
422
  postgresai mon targets list # List databases to monitor
387
423
  postgresai mon targets add <conn-string> <name> # Add database to monitor
424
+ # Same, URL kept out of argv and out of the sudo log (read from stdin, not exported),
425
+ # unless sudoers enables I/O logging (log_input), which records stdin:
426
+ printf '%s\n' "$URL" | sudo sh -c 'IFS= read -r PGAI_DB_URL; export PGAI_DB_URL; exec postgresai mon targets add <name>'
427
+ # With log_input, read it from a file of mode 0600 inside the root shell:
428
+ sudo sh -c 'IFS= read -r PGAI_DB_URL < /path/to/db-url; export PGAI_DB_URL; exec postgresai mon targets add <name>'
388
429
  postgresai mon targets remove <name> # Remove monitoring target
389
430
  postgresai mon targets test <name> # Test target connectivity
390
431
  ```
@@ -465,7 +506,7 @@ Tools exposed:
465
506
  - `update_issue_comment`: update an existing comment (args: `{ comment_id, org_id, content?, attachments?, debug? }`).
466
507
  - `upload_file`: upload a local file and return the storage URL plus a ready-to-paste markdown link (args: `{ path, org_id, debug? }`).
467
508
  - `download_file`: download a file from storage (args: `{ url, org_id, output_path?, debug? }`).
468
- - `connect_database`: `pgai connect` as a tool (args: `{ database_url, org_id, provider?, clickhouse_key?, debug? }`). Returns the same JSON (`status`: `connected`, `provisioning`, `disconnecting`, `action_required` or `failed`; `dashboard_url`; `next`). It does not wait for the monitoring box: call it again to see the status. `database_url` must carry its password, and only the query parameters `sslmode`, `channel_binding`, `application_name` (and `password`); `PGAI_MON_PASSWORD`, `PGPASSWORD` and `CLICKHOUSE_KEY_ID` + `CLICKHOUSE_KEY_SECRET` of the server process are not used, a TLS failure is not retried in plaintext, and `--self-hosted` is CLI-only.
509
+ - `connect_database`: `pgai connect` as a tool (args: `{ database_url, org_id, provider?, clickhouse_key?, debug? }`). Returns the same JSON (`status`: `connected`, `provisioning`, `disconnecting`, `action_required` or `failed`; `dashboard_url`; `next`). It does not wait for the monitoring box: call it again to see the status. `database_url` must carry its password, and only the query parameters `sslmode`, `channel_binding`, `application_name` (and `password`); `PGAI_MON_PASSWORD`, `PGPASSWORD` and `CLICKHOUSE_KEY_ID` + `CLICKHOUSE_KEY_SECRET` of the server process are not used, a TLS failure is not retried in plaintext, and `--self-hosted` is CLI-only. For another database on a server PostgresAI already monitors for the organization, an admin `database_url` with `sslmode=require` (or `verify-*`) is enough: PostgresAI fills in the password of `postgres_ai_mon` it keeps.
469
510
 
470
511
  #### `attachments` parameter (issue/comment tools)
471
512
 
@@ -710,8 +751,8 @@ PGPASSWORD=... postgresai checkup \
710
751
 
711
752
  ```json
712
753
  {
713
- "H002": { "contract_version": "1.1.0", "checkId": "H002", "...": "..." },
714
- "F003": { "contract_version": "1.1.0", "checkId": "F003", "...": "..." }
754
+ "H002": { "contract_version": "1.0.0", "checkId": "H002", "...": "..." },
755
+ "F003": { "contract_version": "1.0.0", "checkId": "F003", "...": "..." }
715
756
  }
716
757
  ```
717
758
 
@@ -722,7 +763,7 @@ PGPASSWORD=... postgresai checkup \
722
763
  `postgresai checkup <ID> <conn>`); stdout is then a one-key object.
723
764
  - **stderr** carries only human-readable diagnostics (progress, warnings,
724
765
  errors). It never contains report JSON — machine consumers should read stdout
725
- only. Do not parse stderr as JSON.
766
+ only. Do not parse stderr of `checkup` as JSON (that of `pgai connect` is JSON lines, see above).
726
767
  - **Exit codes**: `0` on success; non-zero when the run fails (connection
727
768
  failure, insufficient permissions, an unknown/unavailable check ID, or a
728
769
  failing check). On a non-zero exit, no JSON report object is written to
@@ -822,7 +863,7 @@ A consumer should accept any report whose `contract_version` shares its **major*
822
863
  and has a **minor ≥** the minimum it was built against. Pin the major, tolerate
823
864
  additive minors, and treat a major bump as a required review.
824
865
 
825
- The current contract version is **`1.1.0`** (1.1.0: a node result without data carries `available` and `reason`).
866
+ The current contract version is **`1.0.0`**.
826
867
 
827
868
  ### Envelope fields
828
869