Skip to content

feat(web): the plans page on production, US prices, buy buttons disabled - #26

Merged
HetCreep merged 7 commits into
mainfrom
lwk-k5-plans-prod
Oct 5, 2026
Merged

HetCreep merged 7 commits into
mainfrom
lwk-k5-plans-prod

Conversation

@HetCreep

@HetCreep HetCreep commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

What changes

  • web/plans.html becomes a production page at https://kolwen.com/plans. It shows the four US monthly prices before tax (Lite $8, Standard $20, Premium $100, Exclusive $200) and the annual price at 10× monthly. Standard opens first; the others open later. Every row carries a disabled "Coming soon" button (Thai: "เร็ว ๆ นี้"). The page has no checkout code, no payment script and no form, and no "Free" plan. It is in English with a Thai twin, uses the production shell, and has no noindex and no preview banner. Regional prices follow.
  • web/sitemap.xml lists /plans, and web/_headers carries its CSP hash.
  • scripts/surface-check.mjs rule 17: no web page may name a Free plan, and no production page may carry a buy control that is not disabled, a payment script or a checkout URL. The attribute check reads disabled as a whole attribute name.
  • Docs: the CHANGELOG, docs/DEPLOY.md and governance/policies.md.

Proof

  • Red-first, 32 cases: 21 bad cases pass the gate before rule 17 and are refused after. Six mutants each bring back their own miss.
  • The disabled boundary is red-first: notdisabled and disabledx are now refused, and a mutant brings that miss back.
  • The surface check, secret gate and the CI roster pass locally.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added a bilingual plans page at /plans with monthly and yearly US pricing for four plans, plus details about annual pricing, taxes, and existing subscription prices.
    • Added English and Thai language controls, with saved language preferences restored when available.
    • Added the plans page to the sitemap. Purchase buttons are marked “Coming soon” and cannot be used to start a purchase.

HetCreep and others added 4 commits October 5, 2026 16:55
… buy button disabled

/plans shows the four plans as US monthly and yearly prices before tax (Lite, Standard,
Premium, Exclusive; a year is ten times the month), Standard marked as opening first, the
price formula, and "regional prices follow" with no figure. Each row's buy control is a real
disabled button that reads "Coming soon" (Thai: "เร็ว ๆ นี้"): no link, no form, no
checkout code, no payment script. No Free plan is named, no token count, no model name.

The page has no preview banner and no noindex; it carries the production shell and footer
of the home page and links only to pages production has. It is listed in the sitemap and
declared a shipped asset; the CSP gains the one hash for its own inline style block (its
script and noscript style are byte-identical to the home page's).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…uy on a production page

Two clauses on the pages the site serves. (a) No tracked web page, preview or production,
names a Free plan or a free tier in either language: the preview rule's Free check, read
over every page. (b) A production page carries no live buy control: every button is
disabled (the two language-toggle buttons are the one allowance), no form or submit-type
input, no link that reads as a buy control, no Paddle script or global, and no URL
attribute naming a Paddle host, a checkout path or a _ptxn query. Each shape has one clause
that owns it, so a mutant removing one lets its own fixture through and no other.

Red first: against the gate as it stood, 21 of the 24 live fixtures slipped through; with
the rule, all 24 are refused or passed as wanted and all 6 mutants reproduce the miss. A
production page that holds no button at all is a finding, not a pass. The stated limits of
each clause sit in the rule's comment.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…tion plans page and rule 17

The CHANGELOG records the production /plans page (static US prices,
disabled Coming soon buttons, indexable, one extra style hash) and
rule 17. docs/DEPLOY.md names the two production pages and what the
sitemap and robots.txt mean for /plans. governance/policies.md lists
the rule's two classes, with the script as the list of record.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The attribute test was built from a plain string, where '\w' is only the letter w, so
the pattern refused a neighbour of w or a hyphen and not a longer attribute name. A live
button written with notdisabled or disabledx passed as disabled. The backslashes are now
doubled, and every other RegExp built from a string in this file was checked: none had
the same slip.

Red first: both witnesses passed the gate before the fix and are refused after; a bare
disabled, disabled="disabled" and the no-attribute, aria-, title= and data- cases behave
as before, and the single-backslash form put back lets both witnesses through.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: d1795a80-a345-4720-a236-7e9d53775659
📥 Commits

Reviewing files that changed from the base of the PR and between 1f3f37d and f08aa4b.

📒 Files selected for processing (1)
  • scripts/surface-check.mjs
📝 Walkthrough

Walkthrough

Adds a bilingual /plans page with four plans and disabled purchase buttons. Lists the page in the sitemap and updates its CSP style policy. Adds surface checks for free-plan wording and active purchase controls.

Changes

Plans page and surface checks

Layer / File(s) Summary
Plans page content and language behavior
web/plans.html
Adds English and Thai plan details, responsive styling, disabled purchase buttons, and language controls that update the displayed language and document language.
Plans page publication
scripts/surface-check.mjs, web/_headers, web/sitemap.xml, docs/DEPLOY.md, CHANGELOG.md
Adds the page to the shipped-asset list and sitemap, adds its inline-style hash to the CSP, and documents its production-page settings.
Free-plan and purchase-control checks
scripts/surface-check.mjs, governance/policies.md, CHANGELOG.md
Adds checks for free-plan wording on tracked web pages and purchase controls, Paddle code, and checkout URLs on production pages. Updates the policy and changelog descriptions.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Feature

Merge Risk: 🔵 Low · up to 1f3f3

The new plans page itself looks safe, with disabled buy buttons and no payment code. The CI check meant to keep it that way has a few gaps that could let a live buy control through, or wrongly reject a valid page. Tightening those patterns is a small follow-up and is worth doing soon.

  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

🚀 Deploying Preview to Cloudflare 🚀

Preview URL: https://lwk-k5-plans-prod-kolwen.hetcreep.workers.dev (commit f08aa4b)

This URL reflects your latest Preview deployment

Preview Deployments by commit

Status Deployment URL Commit Updated (UTC) See this deployment's details
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://cfa95a87-kolwen.hetcreep.workers.dev f08aa4b 2026-10-05T10:25:11.048Z Visit the dashboard ↗
  • Build: Success ✅
  • Deployment: Success ✅

View logs ↗
https://fb1f36d8-kolwen.hetcreep.workers.dev 1f3f37d 2026-10-05T10:11:37.569Z Visit the dashboard ↗

Comment thread scripts/surface-check.mjs Fixed

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 237cffe5-4f77-4f7a-b7d3-5dafabff5206
📥 Commits

Reviewing files that changed from the base of the PR and between b2bab8c and 1f3f37d.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • docs/DEPLOY.md
  • governance/policies.md
  • scripts/surface-check.mjs
  • web/_headers
  • web/plans.html
  • web/sitemap.xml

Included review availability: This review used your included allowance. 4 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.

📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Workers Builds: kolwen
🧰 Additional context used
📓 Path-based instructions (6)
Kolwen's page served from Cloudflare Workers, and its deploy-kit master in .github.

⚙️ CodeRabbit configuration file

Files:

  • web/sitemap.xml
  • web/_headers
  • web/plans.html
Keep a Changelog.

⚙️ CodeRabbit configuration file

Files:

  • CHANGELOG.md
ISO/IEC 27001:2022 and 42001:2023 control-family records that state what is TRUE today; they are not a certification.

⚙️ CodeRabbit configuration file

Files:

  • governance/policies.md
Repo gates and CLIs.

⚙️ CodeRabbit configuration file

Files:

  • scripts/surface-check.mjs
House style is the UNSPACED em dash, an owner ruling, so do not suggest spaced dashes.

⚙️ CodeRabbit configuration file

Files:

  • governance/policies.md
  • CHANGELOG.md
  • docs/DEPLOY.md
Context for every file.

⚙️ CodeRabbit configuration file

Files:

  • web/sitemap.xml
  • governance/policies.md
  • web/_headers
  • CHANGELOG.md
  • docs/DEPLOY.md
  • scripts/surface-check.mjs
  • web/plans.html
🪛 GitHub Check: CodeQL
scripts/surface-check.mjs

[failure] 726-726: Bad HTML filtering regexp
This regular expression does not match script end tags like </script >.

🔇 Additional comments (4)
web/plans.html (1)

1-183: LGTM!

web/_headers (1)

71-74: LGTM!

Also applies to: 101-101

web/sitemap.xml (1)

8-12: LGTM!

governance/policies.md (1)

24-24: 🗄️ Data Integrity & Integration

The checker applies the Free-plan rule to every tracked HTML page under web/ and applies the purchase-control checks only to production pages. The policy scope matches; no correction is needed.

Comment thread scripts/surface-check.mjs Outdated
Comment thread scripts/surface-check.mjs Outdated
Comment thread scripts/surface-check.mjs Outdated
HetCreep and others added 3 commits October 5, 2026 17:19
…text closed with whitespace

The tag filter ended each skipped block at a bare closing tag, so "</script >" or
"</svg >" (which the HTML parser closes on, and which rule 13's own pattern allows) left
the block's text in the visible text: a Free-looking word inside it was refused as if the
page said it, and CodeQL flagged the filter as a bad HTML filtering regexp. The pattern now
closes on the same tag name followed by a word boundary and any attributes.

Red first: an svg with the text "Free plan" closed by "</svg >" was refused before and
passes after; a visible "Free plan" after such a tag, and in plain text, is still refused;
the old pattern put back refuses the first fixture again.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… as the disabled attribute

The test that a button is disabled removed quoted values before looking for the name, but an
unquoted value stayed: data-state=disabled, or data-x = disabled, left the word in the text and
the live button passed as disabled. Values are now removed after any "=", quoted or not.

Red first: three live buttons (an unquoted value on a data attribute, with spaces round the
"=", and on aria-label) passed before and are refused after; a real disabled written "disabled/",
after an unquoted value, and as disabled="disabled" still pass; the old function put back lets
the first one through.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e alt as well as its text

An icon-only link such as <a aria-label="Buy now"><svg></svg></a> has no text for the buy-word
test to read, and its URL need not look like a checkout, so a live buy link passed. The test now
reads the link's aria-label and title and the alt of an image inside it beside its text, in both
languages. A link named only by aria-labelledby or CSS content is still not read; that limit is
in the rule's comment.

Red first: four linked fixtures (aria-label, title, a Thai aria-label, an image alt) passed before
and are refused after; a link labelled "Contact us" and the page's own "Kolwen home" link still
pass; the label check removed lets the first fixture through.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@HetCreep
HetCreep merged commit 3bb0cb5 into main Oct 5, 2026
13 of 14 checks passed
@HetCreep
HetCreep deleted the lwk-k5-plans-prod branch October 5, 2026 10:26
Sign up for free to 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.

2 participants