Index: test/paid-patron.test.js
===================================================================
--- test/paid-patron.test.js	(revision 6cbd0142768e2cd623437742cd6c08cc33fda44f)
+++ test/paid-patron.test.js	(revision c3d12a6f5721ed2faee19362b8d7e0caeea854d5)
@@ -73,4 +73,15 @@
 });
 
+test('patreonUrl: set, kept on unrelated save, cleared on empty', () => {
+  PP.saveOwnerConfig('s2', { clientId: 'c', clientSecret: 's', campaignId: '7', patreonUrl: 'https://patreon.com/x' });
+  assert.equal(PP.patreonUrl('s2'), 'https://patreon.com/x');
+  // a save that does NOT mention patreonUrl (e.g. token refresh) keeps it
+  PP.saveOwnerConfig('s2', { defaultMinCents: 200 });
+  assert.equal(PP.patreonUrl('s2'), 'https://patreon.com/x');
+  // an explicit empty value clears it
+  PP.saveOwnerConfig('s2', { patreonUrl: '' });
+  assert.equal(PP.patreonUrl('s2'), null);
+});
+
 test('deleteEntitlement removes the row (forget-passkey path)', () => {
   Passkey.storeEntitlement({ credentialId: 'cred3', siteId: 's1', publicKey: 'PK', minCents: 100 });
