render-template: mailto validates malformed dot-atom local parts
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 62/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- bun, typescript
- Domain
- backend
Research direction
Start with LOCAL_PART and classifyMailto in packages/render-template/src/links.ts (about lines 352-405), and trace how percent-decoded and multi-address mailto values reach the local-part check. Reproduce with Bun by calling classifyMailto on mailto:[email protected] and mailto:[email protected], which currently return ok:true. Run bun run test packages/render-template to see the failing regression. Done when leading, trailing and consecutive dots are refused (including encoded and list members) while legal dot-separated atoms still pass, and a changeset is added.
Written by the indexing model from the issue text.
Description
Out of scope
Delivery verification, quoted/non-ASCII address support or new mail capabilities.
Context
Package audit on 2026-10-14 found the following concrete root cause. The audit searched all-state brain-kit issue titles/bodies and read the closest candidate comments. Current open issues were rechecked before filing. Audit reproductions are observations, not passing full-suite or mutation receipts.
Classification: correctness. Severity: low. Confidence: high (direct pure-function reproduction).
Evidence: (const LOCAL_PART, packages/render-template/src/links.ts:352-352) describes RFC 5322 dot-atom but is a flat character allowlist including dots, so it admits an empty atom. (export function classifyMailto, packages/render-template/src/links.ts:371-405) uses only that regex for the local part, then returns ok true and a live href.
Reproduction: importing the source directly with Bun and calling classifyMailto on mailto:[email protected], mailto:[email protected], and mailto:[email protected] returns ok:true for all three and preserves each address in href/display/addresses. The ordinary mailto:[email protected] also returns true. Dot-atom requires nonempty atoms separated by dots, so the first three are not the supported local-part syntax. Percent-decoded addresses go through the same check.
Impact: malformed captured/model-authored mail addresses become apparently validated, live email links in every consumer of the shared classifier, including export and UI prose. Opening these links offers an invalid recipient instead of the established inert refusal. This is not a claim that delivery should be verified or that quoted/non-ASCII local parts should be supported.
Acceptance/verification sketch: reject leading/trailing/repeated dots as unparseable, including percent-encoded equivalents and malformed members in multi-address mailto. Keep legal ASCII atoms, permitted punctuation, ordinary dot-separated atoms, domain classification/query stripping and current refusal shapes. A regression test must fail on current source and a validator-bypass mutation must fail after repair.
Tracker match: searched all-state title/body snapshot for mailto, local part, local-part, dot-atom, mail address, invalid email, email validation and email address. Closest: #551, closed UI prose-link policy, and #558, closed export destination disclosure. Read comments on both; these establish shared classifier/query stripping and publication of validated recipients, but do not track local-part grammar repair. Other email/address matches (#167/#208/#236/#608/#616) concern classification fixtures or visitor capture and do not cover it.
Scope
Reject leading/trailing/consecutive dots in the supported ASCII mail local-part grammar.
Acceptance criteria
- Malformed direct and percent-encoded addresses are inert refusals, including malformed members in recipient lists.
- Legal ASCII dot-separated atoms and supported punctuation remain accepted.
- Domain classification, query stripping and existing refusal shapes remain compatible.
- A named behavioral test fails on the current code for the reported reason and passes after the correction; a restored semantic mutation demonstrates that the guard is effective. For pure unused-code cleanup, production-path proof and the caller/export inventory replace a fabricated behavior mutation.
- Implementation updates relevant documentation/citations and supplies the required focused and hosted proof.
Verification
Use deterministic, keyless, offline fixtures and the real operation/runtime at the implicated boundary. Preserve the repository network guards. Source-only or operation-mirroring audit probes do not replace real browser/native-runtime proof where the behavior depends on it.
bun run test packages/render-template
bun run typecheck
bun run lint
bun run check:pr --base origin/main
For UI/render changes, run the relevant pinned browser/layout/accessibility project and inspect rendered output; retain named failing-first and restored mutation receipts. Existing audit module-load failures establish no behavioral failure or green suite. Any missing original-failure reproduction or policy choice is identified by the needs label and must be resolved before marking agent-ready.
Contract impact
Published behavior correction needs a changeset. Preserve existing CLI/MCP/wire/configuration and public signatures. Reassess the integration contract against the final implementation; any contract change needs the relevant documentation, label and CONTRACT: commit prefix, and a breaking change needs a maintainer ruling.
Unscheduled standalone repair. Severity in the audit describes impact, not a release commitment or assigned priority. Related issues are references unless their full epic outcome explicitly owns this repair.
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 0
- Avg merge
- 5h 30m
- Merged PRs (30d)
- 957
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from schlessera/brain-kit
-
agent-ready area: ci area: ui-react priority: p2 type: test
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
schlessera/brain-kit#2615 · 1 comment ·
Maintainers usually reply within 1 day
-
agent-ready area: ci area: docs type: docs
Difficulty 1/5 1-3 hours Newbie friendliness 82/100
schlessera/brain-kit#2612 ·
Maintainers usually reply within 1 day
-
agent-ready area: ui-react priority: p2 type: fix
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
schlessera/brain-kit#2605 ·
Maintainers usually reply within 1 day
-
agent-ready area: ui-kit priority: p3 type: fix
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
schlessera/brain-kit#2598 ·
Maintainers usually reply within 1 day
-
agent-ready area: ui-react priority: p3 type: refactor
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
schlessera/brain-kit#2597 ·
Maintainers usually reply within 1 day
All issues in schlessera/brain-kit
Similar issues
-
bug skills
Difficulty 2/5 1-3 hours Newbie friendliness 77/100
equinor/fusion-framework#5846 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 74/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Eyevinn/open-videocore#1256 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Maintainers usually reply within 1 day
-
[Bug]: Theme preset geist points at undefined --font-geistPossibly taken @claude claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
Maintainers usually reply within 1 day