Merge main and retain artifact sync write stamps

Signed-off-by: Daniel Rouleau <drouleau@squareup.com>
This commit is contained in:
Daniel Rouleau
2026-10-22 09:46:25 -07:00
33 changed files with 2164 additions and 1310 deletions

View File

@@ -6,7 +6,7 @@ after the schema, indexes, and every serving writer are upgraded.
## Schema and indexes
Migration `0069` adds columns with constant defaults, then changes the defaults
Migration `0070` adds columns with constant defaults, then changes the defaults
for future inserts. It does not rewrite existing rows or run a backfill.
Old rows remain at the epoch timestamp. An initial read includes them.
New application writers stamp every head change, grant, rejoin, removal,
@@ -14,15 +14,15 @@ redaction, and move source. Old application updates do not maintain all these
stamps, so mixed-version serving cannot advertise incremental correctness.
For a populated database, first build the revision lookup index outside a
transaction, before migration `0068`:
transaction, before migration `0069`:
```sql
CREATE INDEX CONCURRENTLY idx_artifact_revisions_artifact
ON public.artifact_revisions (community_id, artifact_id);
```
Apply `0068_artifact_revision_lookup.sql` in a transaction after that prebuild.
Then apply `0069_artifact_sync_timestamps.sql` in a
Apply `0069_artifact_revision_lookup.sql` in a transaction after that prebuild.
Then apply `0070_artifact_sync_timestamps.sql` in a
transaction with its lock and statement budgets. The migration is idempotent
for this prebuild step. Then build these indexes outside a transaction:
@@ -38,15 +38,15 @@ CREATE INDEX CONCURRENTLY artifact_revisions_moves
WHERE source_channel_id IS NOT NULL;
```
Migration `0070` verifies each index definition and its valid, ready, and live
Migration `0071` verifies each index definition and its valid, ready, and live
flags. It refuses a populated table whose index is missing. A fresh empty
database can build the indexes under the migration's short budgets.
Migration `0068` also verifies the exact definition and all three flags.
Migration `0069` also verifies the exact definition and all three flags.
Remove an invalid index with `DROP INDEX CONCURRENTLY` before a new build.
After all index builds succeed, run `buzz-admin migrate` with the target
`DATABASE_URL`. It verifies and records `0068`, reapplies the idempotent `0069`,
then verifies and records `0070`. Direct SQL application does not record the
`DATABASE_URL`. It verifies and records `0069`, reapplies the idempotent `0070`,
then verifies and records `0071`. Direct SQL application does not record the
migration ledger.
## Enable and rollback

View File

@@ -0,0 +1,72 @@
# Submit a synthetic user-deletion request
This first slice saves and reads requests. It does not discover users, build
inventory, approve requests, start workers, or delete data. Only synthetic
`demo:` labels are accepted.
## Prepare a local database
From the repository root, activate Hermit and start a separate PostgreSQL
container. These are disposable local credentials.
```bash
. ./bin/activate-hermit
docker run --detach --name buzz-user-deletion-intake \
--publish 127.0.0.1:55433:5432 \
--env POSTGRES_USER=buzz \
--env POSTGRES_PASSWORD=buzz-local-demo \
--env POSTGRES_DB=buzz postgres:17-alpine
export DATABASE_URL=postgres://buzz:buzz-local-demo@127.0.0.1:55433/buzz
cargo build -p buzz-admin
# Wait for "accepting connections" before migrating.
docker exec buzz-user-deletion-intake pg_isready -U buzz -d buzz
./target/debug/buzz-admin migrate
```
Use an unused port and container name if these are occupied. The commands below
need only PostgreSQL; a relay, Redis, and object storage are unnecessary.
## Submit and see the row
```bash
./target/debug/buzz-admin user-deletions submit \
--target demo:alice --requested-by operator-a
```
The command prints the saved row as JSON. It contains:
| Field | Value |
| --- | --- |
| `id` | New UUID; copy this for inspection |
| `entity_type` | `user` |
| `target` | `demo:alice` |
| `status` | `submitted` |
| `requested_by` | `operator-a` |
| `reason` | `null`, unless supplied with `--reason` |
| `created_at` | Submission time |
| `updated_at` | Same time; no execution has started |
List recent requests, then inspect the UUID returned above:
```bash
./target/debug/buzz-admin user-deletions list --limit 10
REQUEST_ID=<returned-uuid>
./target/debug/buzz-admin user-deletions inspect "$REQUEST_ID"
```
To see the PostgreSQL row directly:
```bash
docker exec buzz-user-deletion-intake psql -X -U buzz -d buzz -c \
"SELECT id, entity_type, target, status, requested_by, created_at
FROM entity_deletion_requests ORDER BY created_at DESC;"
```
Exactly one row is saved in `entity_deletion_requests`. Repeating the same
target, operator, and reason returns that row without changing its timestamps.
Reusing the target with a different operator or reason fails and preserves the
original row. Use a new `demo:` label for a new request.
This slice stops at `submitted`. Inventory, approval, stage history, worker
ownership, and execution will be added in later changes. Their fields and tables
can be added through normal additive migrations.