fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix: the last four places we still promise things we do not do - #82

Open
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims
Open

fix: the last four places we still promise things we do not do#82
cport1 wants to merge 3 commits into
mainfrom
fix/honest-cloud-claims

Conversation

@cport1

Copy link
Copy Markdown
Contributor

Companion to WebDecoy/app#761. Copy only, no behaviour change, no version bump.

The claim that keeps coming back

#476 withdrew blocking from the cross-site actor feed after measuring it against production: 2 of 4,866 addresses ever seen at more than one site, 93% of attacker addresses gone inside an hour, 82% of feed entries already a week stale, none still active. Blocking an abandoned address does not stop the attacker, it stops whoever holds it now.

That fix landed here in 2.3.2. purge_feed_blocks() deletes the rows earlier versions wrote, and both connected variants of the CRITICAL notice were rewritten with a comment above them:

Must not claim Pro would have BLOCKED this. Since 2.3.2 the cross-site feed is advisory and writes nothing to the block list, on any plan.

Four lines below that comment, the unconnected variant went on offering "and to block threats like it automatically" for another three weeks.

A comment asking the next person not to do something is not a guard. There is now a test: it reads every translatable string in the file and fails on one promising to block, prevent or stop anything. Comments in the file discuss blocking at length and are deliberately exempt. Verified by putting the sentence back:

✗ no translatable string in the file offers to block anything
copy promises "block" — the feed is advisory on every plan and writes
nothing to the block list (#476): A CRITICAL deception trap was just
tripped. Connect to WebDecoy Cloud to see whether this attacker is already
known across the network, and to block threats like it automatically.

The wordpress.org listing

Live on the directory today, so these are the ones a stranger reads.

  • "Webhooks & Alerts: automated response chains, email notifications." The API refuses per-detection email (#702). Decoys are public bait and a busy site records thousands of hits a day, so "email me on every detection" is a mailbox nobody reads. Now: automated response chains plus a monthly email report.
  • "Push confirmed attackers to Cloudflare or AWS WAF." True, and it happens in the dashboard. Stated without that, in a plugin readme, it reads like something the plugin does. The claim keeps its substance and gains its location.
  • "Start Free Trial" → "Create a free account". There is no trial on this channel: a connected site is Free Connected, free, indefinitely. Sending someone to a trial they cannot start is a dead end at the exact moment they decided to sign up.
  • The settings upsell said "email alert automation" for the same reason, now the webhook plus the monthly report.

Release

95 tests pass, php -l clean on both touched PHP files.

Nothing here changes behaviour, so no version bump. The readme correction only reaches wordpress.org after an SVN sync, which is a separate deliberate step and not part of this PR.

Refs WebDecoy/app#759, WebDecoy/app#476, WebDecoy/app#702

#476 withdrew blocking from the cross-site actor feed after measuring it
against production: 2 of 4,866 addresses were ever seen at more than one
site, 93% of attacker addresses were gone inside an hour, and 82% of feed
entries were already a week stale with none still active. Blocking an
abandoned address does not stop the attacker, it stops whoever holds it now.
purge_feed_blocks() deletes the rows earlier versions wrote, and the two
connected variants of the CRITICAL notice were rewritten with a comment above
them saying not to claim a block. The unconnected variant went on offering
"to block threats like it automatically" for another three weeks, four lines
below that comment. A comment asking the next person not to do something is
not a guard, so there is now a test: it reads every translatable string in
the file and fails on one that promises to block, prevent or stop anything.
Verified by putting the sentence back.
The listing on wordpress.org had two more. It sold "email notifications",
which the API refuses (#702) because decoys are public bait and a busy site
records thousands of hits a day; email is the monthly report. And it said
attackers get pushed to Cloudflare or AWS WAF without saying that happens in
the dashboard, which reads, in a plugin readme, like something the plugin
does. Both corrected; the WAF claim keeps its substance and gains its
location. "Start Free Trial" is now "Create a free account", because there
is no trial on this channel: connecting is free and stays free.
The settings upsell claimed "email alert automation" for the same reason and
is now the webhook plus the monthly report.
No behaviour changes, so no version bump. The readme correction is live on
wordpress.org only after an SVN sync, which is a separate deliberate step.
Refs #759, #476, #702
The alerts entitlement is served to every paid plan and the plugin has never
read it. A site that upgraded got a flag it could not see and a feature it
could not find.
The Cloud tab now says which it is. On Pro: alerts are on, with a link to the
dashboard where they are configured. On the free tier: what they are and that
detection, blocking and the monthly report stay free, because the answer to
"what do I lose by not paying" should be on the same line as the pitch.
The plugin still sends nothing itself. That is deliberate and is the PRD's
§9 guardrail: an entitlement check may gate a cloud response and never local
behaviour. Everything this plugin does on its own keeps working on every
plan, including with no account at all.
Refs WebDecoy/app#762
@cport1

Copy link
Copy Markdown
ContributorAuthor

Added a second commit: the Cloud tab now reads features.alerts and says whether Slack and webhook alerts are on, with a link to where they are configured.

That flag has been served true to paid plans since P0 and read by nothing, here or anywhere. The companion is WebDecoy/app#764, which makes it mean something in the backend and the rule-engine.

The plugin still sends nothing itself, deliberately: the PRD's §9 guardrail is that an entitlement check gates a cloud response and never local behaviour. Everything this plugin does on its own keeps working on every plan, including with no account.

The free-tier line names what stays free rather than only what is missing. "What do I lose by not paying" belongs on the same line as the pitch.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@cport1