Преглед на файлове

docs: finish the stale-contract audit

Correct the remaining references to CHECK/FK being discarded, RETURNING being
rejected, TLS being declined, and duplicate detection being primary-key-only.
Docs Bot преди 1 ден
родител
ревизия
22b8b0a340

+ 1 - 1
src/content/docs/clients/api-keys.md

@@ -78,7 +78,7 @@ Revoking a key takes effect immediately; any application using it loses access o
 
 - Keys are stored hashed; only the prefix is visible after creation.
 - `DB_ACCESS` and `REST_API` keys are bound to a database. Reserved platform keys are organization-level.
-- A key used for the Postgres protocol is sent as a cleartext password to the proxy, and the proxy currently declines TLS — factor that into how you handle the connection (see [Connect](/getting-started/connect/)).
+- A key used for the Postgres protocol is sent as the password to the proxy. TLS terminates at the proxy when the deployment installs a certificate (`sslmode=require`); without one the key crosses the client-to-proxy hop in cleartext. The proxy-to-engine loopback hop is always plaintext (see [Connect](/getting-started/connect/)).
 
 ## Next
 

+ 2 - 2
src/content/docs/clients/javascript.md

@@ -13,7 +13,7 @@ export PZ_API_KEY='pz_live_REPLACE_ME'
 
 ## With `pg` (Node.js)
 
-The `pg` driver (node-postgres) gives you a real connection pool and transaction support. The database name includes the `/`, and TLS is disabled.
+The `pg` driver (node-postgres) gives you a real connection pool and transaction support. The database name includes the `/`. node-postgres has `ssl: false` by default, which works in `optional` TLS mode; when the proxy requires TLS, set `ssl: true` (or provide a CA) and expect `08P01` until you do.
 
 ```bash
 npm install pg
@@ -28,7 +28,7 @@ const client = new Client({
   user: 'u',                       // ignored; any value
   password: process.env.PZ_API_KEY,
   database: 'acme/production',     // discrete field — no %2F encoding
-  ssl: false,                      // TLS is declined by the proxy
+  ssl: false,                      // set true when the proxy requires TLS
 });
 
 await client.connect();

+ 1 - 1
src/content/docs/clients/postgresql.md

@@ -148,7 +148,7 @@ The SQL you send is **SQLite-compatible**, not PostgreSQL. That means:
 - `INTEGER PRIMARY KEY`, not `SERIAL`; values are assigned when omitted.
 - `TEXT`, not `VARCHAR(n)` with enforced length.
 - No schemas, roles, `ARRAY`, `JSONB`, or `ENUM` types.
-- No `RETURNING`-heavy Postgres-specific features; check [Compatibility](/sql-reference/compatibility/) first.
+- `RETURNING` works for `INSERT`, `UPDATE`, and `DELETE`; PostgreSQL-specific features such as `JSONB` and arrays do not — check [Compatibility](/sql-reference/compatibility/) first.
 
 The [SQL reference](/sql-reference/overview/) is the source of truth for what's supported.
 

+ 2 - 1
src/content/docs/engine/transactions.md

@@ -53,7 +53,8 @@ COMMIT;                -- keeps the first insert
 On the PostgreSQL protocol, the connection tracks transaction state. If a statement inside a transaction block errors:
 
 - The connection enters a "failed transaction" state and rejects further commands with SQLSTATE `25P02` until the client sends `ROLLBACK` (or `ROLLBACK TO SAVEPOINT`).
-- This mirrors PostgreSQL's aborted-transaction behaviour.
+- A failed **`COMMIT`** is different: storage has already rolled the transaction back, so the session returns to idle and the next statement starts a new implicit transaction. Do not keep issuing `ROLLBACK` after a failed commit.
+- This mirrors PostgreSQL's aborted-statement behaviour.
 
 ## Managed service restrictions
 

+ 1 - 1
src/content/docs/guides/errors.md

@@ -83,7 +83,7 @@ Common causes:
 
 - **`no such table`** — the table doesn't exist yet, or you're connected to the wrong database.
 - **`syntax error`** — a typo, or Postgres-only syntax. PizzaSQL uses SQLite-compatible SQL; check [Compatibility](/sql-reference/compatibility/).
-- **`duplicate primary key`** — an insert reused an existing primary-key value. Other `UNIQUE` constraints are not enforced.
+- **`duplicate primary key`** — an insert reused an existing primary-key value. `UNIQUE` constraints and unique indexes are enforced too and return SQLSTATE `23505` on the PostgreSQL path.
 - **`NOT NULL constraint failed`** — a `NULL` value in a `NOT NULL` column.
 
 ## Transactions over HTTP

+ 1 - 1
src/content/docs/internals/catalog.md

@@ -41,7 +41,7 @@ This means concurrent DDL and DML from different connections eventually converge
 
 The catalog is deliberately minimal:
 
-- It does **not** store `CHECK` or `FOREIGN KEY` constraints — those are discarded at `CREATE TABLE`. `UNIQUE` constraints are materialized into unique index definitions (see [Constraints](/sql-reference/constraints/)).
+- It does **not** store `CHECK` or `FOREIGN KEY` constraints — those DDL clauses are rejected at `CREATE TABLE` with SQLSTATE `0A000`. `UNIQUE` constraints are materialized into unique index definitions (see [Constraints](/sql-reference/constraints/)).
 - It does not store index definitions (those live in the `SchemaManager`/storage, not the analyzer catalog).
 - It does not store statistics, histograms, or anything a cost-based planner would use — there is no planner.
 

+ 1 - 1
src/content/docs/internals/query-lifecycle.md

@@ -7,7 +7,7 @@ This page traces a single statement from bytes to result. It explains *why* cert
 
 ## 1. Lex and parse
 
-The SQL string is tokenized and parsed into an AST. Both steps are pure and fail fast with a syntax error for anything the grammar doesn't cover (`RETURNING`, `WITHOUT ROWID`, triggers, etc.). A statement that parses is guaranteed to be one the engine at least *recognizes*, even if it later turns out to be only partially implemented.
+The SQL string is tokenized and parsed into an AST. Both steps are pure and fail fast with a syntax error for anything the grammar doesn't cover (`WITHOUT ROWID`, triggers, etc.). A statement that parses is guaranteed to be one the engine at least *recognizes*, even if it later turns out to be only partially implemented.
 
 Over the PostgreSQL protocol, a multi-statement batch is parsed *in full before execution begins*, so an unsupported trailing statement doesn't leave earlier writes half-committed.
 

+ 2 - 2
src/content/docs/sql-reference/constraints.md

@@ -1,6 +1,6 @@
 ---
 title: Constraints
-description: What PRIMARY KEY, NOT NULL, DEFAULT, UNIQUE, CHECK, and FOREIGN KEY actually do in PizzaSQL — and which ones are not enforced.
+description: What PRIMARY KEY, NOT NULL, DEFAULT, UNIQUE, CHECK, and FOREIGN KEY actually do in PizzaSQL — and which ones are rejected.
 ---
 
 Constraints in PizzaSQL fall into two camps: the ones that are actually implemented, and the ones that merely parse. This page is deliberately blunt about the difference, because silently assuming a `CHECK` or `FOREIGN KEY` constraint is enforced will corrupt data. `UNIQUE` is now enforced on the core write paths, with caveats described below.
@@ -13,7 +13,7 @@ Constraints in PizzaSQL fall into two camps: the ones that are actually implemen
 - A composite primary key (`PRIMARY KEY (a, b)`) is rejected at `CREATE TABLE` with SQLSTATE `0A000`; it is never silently reduced to the first column.
 - An **`INTEGER PRIMARY KEY`** column becomes an alias for the implicit rowid. Inserting without a value auto-assigns the next rowid; inserting with a value sets the rowid and advances the counter past it.
 - A **non-integer primary key** (e.g. `TEXT PRIMARY KEY`) is a normal column with a separate hidden rowid counter.
-- The primary key drives **duplicate detection** on `INSERT`, and therefore `INSERT OR REPLACE`/`OR IGNORE` and `ON CONFLICT DO NOTHING`/`DO UPDATE` — all of which are keyed on the primary key only.
+- The primary key and unique indexes drive **duplicate detection** on `INSERT`, and therefore `INSERT OR REPLACE`/`OR IGNORE` and `ON CONFLICT DO NOTHING`/`DO UPDATE`. `ON CONFLICT` targets a primary key or unique-index column list.
 - Without any declared primary key, the engine assigns a synthetic `_rowid_` primary key, so duplicate and NULL values are allowed in user columns.
 
 ### NOT NULL