mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
fix: bind deletion approval to frozen inventory digest
Co-authored-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz> Signed-off-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@buzz.block.builderlab.xyz>
This commit is contained in:
parent
e00dee77e2
commit
79536ff35f
@@ -689,7 +689,7 @@ jobs:
|
||||
run: |
|
||||
cargo nextest run \
|
||||
--archive-file target/ci/backend-integration-tests.tar.zst \
|
||||
-E '(package(buzz-deletion) and test(/tests::/)) or (package(buzz-relay) and test(/finalize_push_(holds_serving_lease_through_post_cas_publication|db_failure_after_cas_is_not_success_and_releases_lease)/))' \
|
||||
-E '(package(buzz-deletion) and test(/tests::/)) or (package(buzz-db) and test(/deletion::postgres_tests/)) or (package(buzz-relay) and test(/finalize_push_(holds_serving_lease_through_post_cas_publication|db_failure_after_cas_is_not_success_and_releases_lease)/))' \
|
||||
--run-ignored ignored-only
|
||||
env:
|
||||
DATABASE_URL: postgres://buzz:${{ env.BUZZ_TEST_POSTGRES_PASSWORD }}@localhost:5432/buzz
|
||||
|
||||
@@ -2440,6 +2440,18 @@ mod postgres_tests {
|
||||
.expect("live schema after row churn");
|
||||
assert_eq!(current_schema, inventory.schema);
|
||||
|
||||
let mismatched_insert = sqlx::query(
|
||||
"INSERT INTO community_deletion_approvals \
|
||||
(request_id, inventory_digest, approved_by) VALUES ($1, $2, 'tampered')",
|
||||
)
|
||||
.bind(request.id)
|
||||
.bind(vec![0_u8; 32])
|
||||
.execute(&db.pool)
|
||||
.await;
|
||||
assert!(
|
||||
mismatched_insert.is_err(),
|
||||
"a mismatched approval must be unrepresentable"
|
||||
);
|
||||
let approved = store
|
||||
.approve(request.id, "approver-a", Some("reviewed"))
|
||||
.await
|
||||
@@ -2449,6 +2461,28 @@ mod postgres_tests {
|
||||
approved.inventory_digest,
|
||||
Some(hex::encode(inventory.digest().unwrap()))
|
||||
);
|
||||
let mismatched_approval = sqlx::query(
|
||||
"UPDATE community_deletion_approvals SET inventory_digest = $2 WHERE request_id = $1",
|
||||
)
|
||||
.bind(request.id)
|
||||
.bind(vec![0_u8; 32])
|
||||
.execute(&db.pool)
|
||||
.await;
|
||||
assert!(
|
||||
mismatched_approval.is_err(),
|
||||
"approval digest must remain database-bound to the frozen request digest"
|
||||
);
|
||||
let mismatched_request = sqlx::query(
|
||||
"UPDATE community_deletion_requests SET inventory_digest = $2 WHERE id = $1",
|
||||
)
|
||||
.bind(request.id)
|
||||
.bind(vec![1_u8; 32])
|
||||
.execute(&db.pool)
|
||||
.await;
|
||||
assert!(
|
||||
mismatched_request.is_err(),
|
||||
"the frozen request digest must remain bound to its approval"
|
||||
);
|
||||
assert!(store
|
||||
.claim_specific(request.id, "executor-a", DEFAULT_LEASE_DURATION)
|
||||
.await
|
||||
|
||||
@@ -49,7 +49,8 @@ CREATE TABLE community_deletion_requests (
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
completed_at TIMESTAMPTZ,
|
||||
CHECK ((blocked_at IS NULL) = (blocked_reason IS NULL)),
|
||||
CHECK ((inventory_frozen_at IS NULL) = (inventory_digest IS NULL))
|
||||
CHECK ((inventory_frozen_at IS NULL) = (inventory_digest IS NULL)),
|
||||
UNIQUE (id, inventory_digest)
|
||||
);
|
||||
CREATE INDEX community_deletion_requests_runnable
|
||||
ON community_deletion_requests (next_attempt_at, created_at)
|
||||
@@ -61,11 +62,14 @@ CREATE INDEX community_deletion_requests_lease
|
||||
WHERE lease_owner IS NOT NULL;
|
||||
|
||||
CREATE TABLE community_deletion_approvals (
|
||||
request_id UUID PRIMARY KEY REFERENCES community_deletion_requests(id) ON DELETE RESTRICT,
|
||||
request_id UUID PRIMARY KEY,
|
||||
inventory_digest BYTEA NOT NULL CHECK (length(inventory_digest) = 32),
|
||||
approved_by TEXT NOT NULL,
|
||||
note TEXT,
|
||||
approved_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
approved_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
FOREIGN KEY (request_id, inventory_digest)
|
||||
REFERENCES community_deletion_requests(id, inventory_digest)
|
||||
ON DELETE RESTRICT
|
||||
);
|
||||
|
||||
CREATE TABLE community_deletion_checkpoints (
|
||||
|
||||
+7
-3
@@ -1112,7 +1112,8 @@ CREATE TABLE community_deletion_requests (
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
completed_at TIMESTAMPTZ,
|
||||
CHECK ((blocked_at IS NULL) = (blocked_reason IS NULL)),
|
||||
CHECK ((inventory_frozen_at IS NULL) = (inventory_digest IS NULL))
|
||||
CHECK ((inventory_frozen_at IS NULL) = (inventory_digest IS NULL)),
|
||||
UNIQUE (id, inventory_digest)
|
||||
);
|
||||
CREATE INDEX community_deletion_requests_runnable
|
||||
ON community_deletion_requests (next_attempt_at, created_at)
|
||||
@@ -1123,11 +1124,14 @@ CREATE INDEX community_deletion_requests_lease
|
||||
ON community_deletion_requests (lease_until) WHERE lease_owner IS NOT NULL;
|
||||
|
||||
CREATE TABLE community_deletion_approvals (
|
||||
request_id UUID PRIMARY KEY REFERENCES community_deletion_requests(id) ON DELETE RESTRICT,
|
||||
request_id UUID PRIMARY KEY,
|
||||
inventory_digest BYTEA NOT NULL CHECK (length(inventory_digest) = 32),
|
||||
approved_by TEXT NOT NULL,
|
||||
note TEXT,
|
||||
approved_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
approved_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
FOREIGN KEY (request_id, inventory_digest)
|
||||
REFERENCES community_deletion_requests(id, inventory_digest)
|
||||
ON DELETE RESTRICT
|
||||
);
|
||||
CREATE TABLE community_deletion_checkpoints (
|
||||
request_id UUID NOT NULL REFERENCES community_deletion_requests(id) ON DELETE RESTRICT,
|
||||
|
||||
Reference in New Issue
Block a user