From d2f056bd2096ef00d91ee40e2034477cd1523c82 Mon Sep 17 00:00:00 2001 From: Pavel Mamut Date: Wed, 25 Feb 2026 16:24:30 -0500 Subject: [PATCH 1/3] first crack at story name & description retraction to consider: updating `String.Hash` and `LongString.Hash` with corresponding values --- one-off/redact-story-name-and-description.sql | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 one-off/redact-story-name-and-description.sql diff --git a/one-off/redact-story-name-and-description.sql b/one-off/redact-story-name-and-description.sql new file mode 100644 index 0000000..ceac91a --- /dev/null +++ b/one-off/redact-story-name-and-description.sql @@ -0,0 +1,59 @@ +declare @saveChanges bit; -- set @saveChanges=1 +declare @storyNumber int=NNNNN + +declare @storyId int +select @storyId=ID from dbo.Workitem_Now where AssetType='Story' and Number=@storyNumber + +if (@storyId is null) begin + raiserror('S-%d not found', 16, 1, @storyNumber) + return +end +raiserror('Found Story:%d', 0, 1, @storyId) with nowait + +declare @storyOid varchar(max)='Story:'+cast(@storyId as varchar(max))+':%' + +set nocount on; begin tran; save tran tx +declare @error int, @rowcount int + +update dbo.String +set Value=N'redacted' +from dbo.BaseAsset +where String.ID=Name and BaseAsset.ID=storyId + +select @rowcount=@@ROWCOUNT, @error=@@ERROR +if @error<>0 goto ERR +raiserror('%d Names redacted', 0, 1, @rowcount) with nowait + +update dbo.LongString +set Value = N'redacted' +from dbo.BaseAsset +where LongString.ID=Description and BaseAsset.ID=@storyId + +select @rowcount=@@ROWCOUNT, @error=@@ERROR +if @error<>0 goto ERR +raiserror('%d Descriptions redacted', 0, 1, @rowcount) with nowait + +delete dbo.Commits +where cast(Payload as varchar(max)) like '%Asset":"'+@storyOid and ( + cast(Payload as varchar(max)) like '%"Name":"Name"%' or + cast(Payload as varchar(max)) like '%"Name":"Description"%' +) + +select @rowcount=@@ROWCOUNT, @error=@@ERROR +if @error<>0 goto ERR +raiserror('%d Commits deleted', 0, 1, @rowcount) with nowait + +delete dbo.WebhookEvents +where cast(Payload as varchar(max)) like '%oid":"'+@storyOid and ( + cast(Payload as varchar(max)) like '%"name":"Name"%' or + cast(Payload as varchar(max)) like '%"name":"Description"%' +) + +select @rowcount=@@ROWCOUNT, @error=@@ERROR +if @error<>0 goto ERR +raiserror('%d WebhookEvents deleted', 0, 1, @rowcount) with nowait + +if @saveChanges=1 goto OK +raiserror('Rolling back changes. To commit changes, set @saveChanges=1', 16, 1) +ERR: rollback tran tx +OK: commit From 5ce14caee6ed9778e7627b63585f1af48086fec6 Mon Sep 17 00:00:00 2001 From: Pavel Mamut Date: Wed, 25 Feb 2026 16:35:44 -0500 Subject: [PATCH 2/3] update corresponding `String` and `LongString` hash values to consider: duplicated `redacted` values? --- one-off/redact-story-name-and-description.sql | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/one-off/redact-story-name-and-description.sql b/one-off/redact-story-name-and-description.sql index ceac91a..02cce54 100644 --- a/one-off/redact-story-name-and-description.sql +++ b/one-off/redact-story-name-and-description.sql @@ -11,12 +11,15 @@ end raiserror('Found Story:%d', 0, 1, @storyId) with nowait declare @storyOid varchar(max)='Story:'+cast(@storyId as varchar(max))+':%' +declare @redacted nvarchar(max)=N'redacted' +declare @hash int=BINARY_CHECKSUM(@redacted) +declare @longHash binary(20)=cast(hashbytes('SHA2_512', @redacted) as binary(20)) set nocount on; begin tran; save tran tx declare @error int, @rowcount int update dbo.String -set Value=N'redacted' +set Value=@redacted, Hash=@hash from dbo.BaseAsset where String.ID=Name and BaseAsset.ID=storyId @@ -25,7 +28,7 @@ if @error<>0 goto ERR raiserror('%d Names redacted', 0, 1, @rowcount) with nowait update dbo.LongString -set Value = N'redacted' +set Value=@redacted, Hash=@longHash from dbo.BaseAsset where LongString.ID=Description and BaseAsset.ID=@storyId From 92562d101add541c921fac0643fa0356b3997f66 Mon Sep 17 00:00:00 2001 From: Rajiv Delwadia Date: Thu, 26 Feb 2026 06:41:30 -0700 Subject: [PATCH 3/3] add header block --- one-off/redact-story-name-and-description.sql | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/one-off/redact-story-name-and-description.sql b/one-off/redact-story-name-and-description.sql index 02cce54..6c33a7c 100644 --- a/one-off/redact-story-name-and-description.sql +++ b/one-off/redact-story-name-and-description.sql @@ -1,5 +1,18 @@ -declare @saveChanges bit; -- set @saveChanges=1 +/* + * Redact the name and description of a story, + * along with any commits or webhook events that contain the name or description in their payload. + * + * INSTRUCTIONS: + * 1. Set @storyNumber to the Story number to redact + * 2. Review the messages printed by the script to verify that it is updating the expected records + * 3. Set @saveChanges=1 + * 4. Rerun the script to commit the changes + * + * NOTE: This script defaults to rolling back changes. + * To commit changes, set @saveChanges = 1. + */ declare @storyNumber int=NNNNN +declare @saveChanges bit; --set @saveChanges = 1 declare @storyId int select @storyId=ID from dbo.Workitem_Now where AssetType='Story' and Number=@storyNumber