Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,9 @@ current state rather than treating a dated snapshot as a permanent fact.
not show the check-inbox notice. Owner mail-test diagnose is read-only and
exact-configured-target scoped, never part of editorial schedules. No private
identifiers or individual delivery records go into public documentation.

- Every Brevo `to` recipient carries `contactPixelTrackingConsent: false` for
public and owner-test confirmation/digest mail. Preserve it if adding cc/bcc;
never retry by removing the flag. Account-side per-contact consent enablement
is a separate prerequisite; final pixel/link removal needs real-mail evidence.
See docs/iterations/2026-10-14-brevo-tracking-consent.md for current verification.
2 changes: 1 addition & 1 deletion EDITORIAL_POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ Sources include official blogs, specifications, release repositories, original r

The older GitHub ecosystem watcher remains a supplementary source-drift issue reporter. Dynamic editorial operations are documented in public/automation.md and use owner-authorized MCP tools backed by D1. Reading a public Site grants no write, mail or subscriber-data permissions.

Email stays pending activation until Brevo free account/domain and real delivery acceptance pass. No new paid services or model APIs. No automatic upgrades, empty digests, tracking pixels or silent retry of uncertain submissions.
Public email activation is recorded in the v12 and v1.0.1 release records; preserve current production gates. Every Brevo recipient explicitly requests no open/click tracking with `contactPixelTrackingConsent: false`. Account-side enablement and complete removal of provider pixels/rewritten links require separate verification; keep bilingual disclosures accurate. Our templates add no tracking resources. No new paid services or model APIs, automatic upgrades, empty digests or silent retry of uncertain submissions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ and waits for its own local Worker before running HTTP tests.

Set secrets only through Sites environment variables. `SITE_OWNER_EMAIL` authorizes the verified Sites owner identity; `ANALYTICS_SECRET` derives daily visitor estimates; `SUBSCRIPTION_SECRET` signs confirmation and management links. Never use a Sites viewer or bypass token as owner authorization.

Email activation requires `BREVO_API_KEY`, `BREVO_SENDER_EMAIL`, `BREVO_WEBHOOK_SECRET`, `BREVO_DOMAIN_VERIFIED=true`, `EMAIL_ACCEPTANCE_PASSED=true` and `EMAIL_ENABLED=true`. Keep `EMAIL_ENABLED` and `EMAIL_ACCEPTANCE_PASSED` false until a real mailbox confirms, receives a digest, changes preferences and unsubscribes, and authenticated callbacks are verified. With the owner's acceptance and accurate public disclosure, anonymous Brevo open/click tracking may remain enabled; anonymizing tracking does not disable pixels or tracked links. The site does not use these statistics to decide whether to send mail or as proof that an email was read. Fully disabling tracking remains a future privacy improvement. Configure transactional webhooks with bearer authentication to `/api/brevo/webhook`; subscribe to delivered, hardBounce, softBounce, spam, invalid, blocked and unsubscribed. Official contracts: [secured webhooks](https://developers.brevo.com/docs/secured-webhooks), [transactional events](https://developers.brevo.com/docs/transactional-webhooks).
Email activation requires `BREVO_API_KEY`, `BREVO_SENDER_EMAIL`, `BREVO_WEBHOOK_SECRET`, `BREVO_DOMAIN_VERIFIED=true`, `EMAIL_ACCEPTANCE_PASSED=true` and `EMAIL_ENABLED=true`. Keep `EMAIL_ENABLED` and `EMAIL_ACCEPTANCE_PASSED` false until a real mailbox confirms, receives a digest, changes preferences and unsubscribes, and authenticated callbacks are verified. Every Brevo recipient explicitly carries `contactPixelTrackingConsent: false`. The account must first enable per-contact pixel tracking consent; set unknown-consent tracking to No. Account enablement and complete removal of pixels/rewritten links require separate verification; the current iteration records that gap. Open/click statistics never decide sending or prove reading. See [email operations](docs/operations/email-subscriptions.md). Configure transactional webhooks with bearer authentication to `/api/brevo/webhook`; subscribe to delivered, hardBounce, softBounce, spam, invalid, blocked and unsubscribed. Official contracts: [secured webhooks](https://developers.brevo.com/docs/secured-webhooks), [transactional events](https://developers.brevo.com/docs/transactional-webhooks).

For real delivery acceptance before public activation, also configure `EMAIL_TEST_RECIPIENT` as a server-side secret containing the one explicitly authorized test address. Keep `EMAIL_ENABLED=false` and `EMAIL_ACCEPTANCE_PASSED=false`. The owner-only `newsroom_write` / `/api/admin` operation `mail-test` requires a verified domain, sender, API key, webhook secret and existing subscription signing secret. It cannot take a recipient argument, enable public email, or drain the production queue. Do not invoke it from scheduled editorial tasks.

Expand Down
4 changes: 2 additions & 2 deletions app/[locale]/privacy/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ export default async function Privacy({
<h2>{zh ? "邮件订阅" : "Email subscriptions"}</h2>
<p>
{zh
? "邮箱用于确认订阅、精选周报和订阅偏好;订阅须完成邮件确认后才生效,可选择语言与主题。邮件由 Brevo 投递,当前匿名打开与点击统计不关联具体联系人,但邮件仍可能包含打开像素与链接跟踪。本站不依据这些统计决定发信,也不将其作为已读证明。每封邮件提供退订与偏好链接;退订、投诉和硬退信将停止后续投递。"
: "Email addresses are used for confirmation, the weekly digest and subscription preferences. A subscription takes effect only after email confirmation, and subscribers can choose their language and topics. Brevo delivers email; its current anonymous open and click statistics are not associated with individual contacts, but emails may still contain tracking pixels and tracked links. This site does not use these statistics to decide whether to send email or as proof that an email was read. Every email includes unsubscribe and preference links. Unsubscribes, complaints and hard bounces stop future delivery."}
? "邮箱用于确认订阅、精选周报和订阅偏好;订阅须完成邮件确认后才生效,可选择语言与主题。邮件由 Brevo 投递。本站对每位收件人明确要求关闭打开与点击跟踪;最终邮件是否完全移除像素与链接改写仍待验证,不承诺邮件完全无跟踪。本站不依据打开或点击统计决定发信,也不将其作为已读证明。每封邮件提供退订与偏好链接;退订、投诉和硬退信将停止后续投递。"
: "Email addresses are used for confirmation, the weekly digest and subscription preferences. A subscription takes effect only after email confirmation, and subscribers can choose their language and topics. Brevo delivers email. We explicitly request no open/click tracking for each recipient. Complete removal of pixels and rewritten links from delivered mail remains unverified; we do not promise tracking-free email. Open/click statistics do not determine sending or prove reading. Every email includes unsubscribe and preference links. Unsubscribes, complaints and hard bounces stop future delivery."}
</p>
<p>
{zh
Expand Down
2 changes: 1 addition & 1 deletion components/news/subscription.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,11 @@
})()}
{form}
{manage && !confirmationMode && (subscriber?.status === "confirmed" || subscriber?.status === "pending") && <section id="unsubscribe" className="n-subscription-form n-subscription-unsubscribe-area" aria-label={zh ? "结束邮件订阅" : "Stop email updates"}><div><h3>{zh ? "取消邮件订阅" : "Cancel email updates"}</h3><p>{zh ? "停止后续邮件;仍可使用 RSS。" : "Stop future email. RSS remains available."}</p></div><button type="button" className="n-subscription-secondary n-subscription-unsubscribe-button" disabled={formLocked} onClick={() => void submit("unsubscribe")}>{busy === "unsubscribe" ? zh ? "正在退订…" : "Unsubscribing…" : subscriber.status === "pending" ? zh ? "取消订阅申请" : "Cancel subscription request" : zh ? "退订所有邮件" : "Unsubscribe from all email"}</button></section>}
<p className="n-small n-subscription-disclosure">{zh ? "邮件由 Brevo 投递。当前匿名打开与点击统计不关联具体联系人,但仍可能包含像素与链接跟踪;本站不依据这些统计决定发信或判断已读。" : "Brevo delivers email. Anonymous opens/clicks are not tied to contacts; tracking pixels and links may remain. These statistics do not determine sending or prove reading."}</p>
<p className="n-small n-subscription-disclosure">{zh ? "邮件由 Brevo 投递。本站要求关闭打开与点击跟踪,不以此判断已读或决定发信;像素与链接改写是否完全移除仍待验证。" : "Brevo delivers email. We request no open/click tracking and do not use it to decide sending or prove reading. Complete pixel/link removal remains unverified."}</p>
</div>
<aside className="n-subscription-sidebar" aria-label={zh ? "RSS 阅读方式" : "Read with RSS"}>
<section className="n-rss-box">
<div className="n-rss-heading"><span className="n-kicker">OPEN FEEDS</span><img src="/brand/rss-feed.svg" width="38" height="38" alt="" aria-hidden="true" /></div>

Check warning on line 303 in components/news/subscription.tsx

View workflow job for this annotation

GitHub Actions / verify

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
<h2>{zh ? "阅读,不止一种方式。" : "Read on your terms."}</h2>
<p>{zh ? "全部已发布新闻,直接进入 RSS 阅读器。无需邮箱,不占名额。" : "All published stories in your RSS reader. No email or subscription place needed."}</p>
<div className="n-rss-feeds">{(["zh", "en"] as const).map(feedLanguage => {
Expand Down
50 changes: 50 additions & 0 deletions docs/CURRENT_STATE.json
Original file line number Diff line number Diff line change
Expand Up @@ -990,5 +990,55 @@
"rolloutLimit": "New client requires subscriptionType; use matching client and Worker and refresh open pages after rollback",
"documentationFollowup": "Receipt-only PR after publication does not redeploy Sites or move the immutable v1.0.0 tag; query GitHub for its eventual commit instead of self-reference"
}
},
"trackingConsentIteration": {
"authorizedOn": "2026-10-14",
"phase": "local-candidate",
"baseMain": "983a21cf579eb11176bd307fc9016286f6ef9780",
"notes": "docs/iterations/2026-10-14-brevo-tracking-consent.md",
"recipientParameter": {
"contactPixelTrackingConsent": false
},
"coverage": [
"confirmation",
"weekly",
"public",
"owner-test",
"zh",
"en"
],
"providerAccountSetting": "pending verification after browser login connection failure",
"completePixelAndLinkRemovalVerified": false,
"realMailSent": false,
"newTagCreated": false,
"schemaChanged": false,
"dnsChanged": false,
"productionMailGatesChanged": false,
"schedulesChanged": false,
"validation": {
"newsAndMail": 69,
"mockProviderOnly": true,
"baseTests": 35,
"subscriptionUi": 12,
"localHttp": 8,
"total": 124,
"typescript": "passed",
"lint": "passed with 2 existing warnings",
"audit": {
"moderate": 8,
"high": 0,
"critical": 0
},
"content": "passed",
"build": "passed",
"bundle": {
"javascriptBytes": 919926,
"javascriptGzipBytes": 267601,
"cssBytes": 116185,
"cssGzipBytes": 23035,
"budgetsPreserved": true
},
"browser": "Local zh/en subscription and privacy; 390x844 en subscription no horizontal overflow; mail disabled"
}
}
}
8 changes: 6 additions & 2 deletions docs/PROJECT_CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

本说明用于在同一个项目中持续迭代。它仅保留可公开的工程事实,未复制私人运营审计、账户、验收邮箱、生产数据或秘密值。机器可读记录见 [CURRENT_STATE.json](CURRENT_STATE.json)。

## 当前发布:v1.0.1(2026-10-13)
## 当前迭代:Brevo 收件人级跟踪退出(2026-10-14)

用户已授权每封邮件收件人设置 `contactPixelTrackingConsent: false`、提交推送并更新应用。确认/周报及公众/测试发信共用入口;双语披露同步说明明确退出请求与实际像素/链接移除证据的区别。账户侧功能尚待安全登录核验,当前已发布版本仍为下述 v17,不能把本地参数当作生产或服务商执行证据。详见 [迭代记录](iterations/2026-10-14-brevo-tracking-consent.md)。

## 最近语义化发布:v1.0.1(2026-10-13)

已完成 [v1.0.1 标签](https://github.com/AutoGenUI/ag-ui.ai/tree/v1.0.1) 推送,固定至发布提交 `fae53ff09c26ca10985e5a48d04a76fc1511046b`,由 [PR #13](https://github.com/AutoGenUI/ag-ui.ai/pull/13) 正常合入。Sites **v17** 于 13:48:23 UTC 正式部署成功,源码 tree 与标签提交一致;env revision 12、公开权限、MCP、两项任务及邮件额度不变。119 项 CI、构建及原预算通过;main 首次本地 HTTP 失败与同提交重跑通过均保留在 [发布回执](releases/v1.0.1.md)。中英订阅页、RSS、公开状态 200,匿名管理 403。工程版本为 1.0.1,本轮不改运行逻辑、不新增真实收件或生产 DOM 验收。下文等待标签的表述均为当时的历史门槛,已由用户本次明确授权覆盖。

Expand Down Expand Up @@ -113,7 +117,7 @@ Sites 数字版本 **14** 于 11:34:36 UTC 部署成功,version ID `appgprj_6a

## 隐私与访问限制

交接记录已接受并披露 Brevo 匿名跟踪。匿名化不等于关闭像素或链接改写;全面关闭尚未验证,订阅与隐私页面必须保持准确的双语披露。本站浏览统计不存原始 IP、不关联订阅邮箱与浏览轨迹,访客数为估算;这是第一方统计的边界,不代表邮件没有第三方跟踪。
交接曾接受并披露 Brevo 匿名跟踪;2026-10-14 用户进一步授权每位收件人发送明确跟踪退出参数。账户侧功能启用及最终邮件像素/链接改写移除仍需核验,订阅与隐私页面必须保持准确的双语披露。本站浏览统计不存原始 IP、不关联订阅邮箱与浏览轨迹,访客数为估算;这是第一方统计的边界,不代表邮件没有第三方跟踪。

中国大陆部分网络的 Cloudflare 拦截为已知限制。后续手机流程曾成功,不证明拦截原因、地域覆盖或全球可访问性。继续保留 Sites;不能从旧的某个出口成功推断所有网络均已恢复。

Expand Down
18 changes: 18 additions & 0 deletions docs/iterations/2026-10-14-brevo-tracking-consent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Brevo 收件人级跟踪退出(2026-10-14)

用户明确授权实施 `contactPixelTrackingConsent: false`、提交推送并更新应用。基线为 main `983a21cf579eb11176bd307fc9016286f6ef9780`、已发布 Sites v17;保留 v1.0.0/v1.0.1 标签,未创建新语义化版本。

## 实现与边界

共享 Brevo `POST /v3/smtp/email` 的 `to` 收件人对象明确携带布尔值 `contactPixelTrackingConsent: false`。确认邮件和周报、中英文、公众与 owner 测试邮件均走此入口。没有添加请求级同名字段、允许跟踪的回退或第二次发送。订阅/退订、配额、抑制、幂等、签名和回调鉴权保持原样;跟踪事件不作为送达或已读证据。

依据 2026-10-14 查阅的 [Brevo 官方说明](https://help.brevo.com/api/v2/help_center/en-us/articles/37113920427922.json),API 参数属于每个 `to`/`cc`/`bcc` 收件人,当前本站仅使用 `to`。该功能还要求先在账户 Settings → Contacts → Per-contact pixel tracking consent 中启用;将未知同意状态跟踪设为 No。此设置不影响 delivered、bounce、spam、invalid、blocked、unsubscribed 等投递/抑制事件。

账户状态核验尚未完成:现有浏览器登录跳转连接失败,已请求所有者安全登录或反馈上述开关状态。不读取密码、会话或密钥;代码发出明确退出请求不等于账户功能已启用。中英订阅页、隐私页和模板同步说明“要求关闭打开与点击跟踪”,并保留最终邮件像素与链接改写是否完全移除的未验证边界。本轮没有发送真实邮件或检查真实 MIME,因此即便账户开关后续确认,也不能据本地 mock 宣称所有客户端完全无跟踪。

## 验证与发布记录

- 隔离数据库和 mock provider:新闻/邮件 69 项通过;新增中英 × 公众/测试四组,验证确认和周报都携带退出参数、投递关联仍在、提交与送达区分、跟踪事件不改变状态、硬退信抑制及额度保留。
- 本地共 124 项通过:35 基础、69 新闻/邮件、12 订阅 UI、8 隔离 Worker HTTP;内容校验、TypeScript、lint、构建与原预算通过。审计仍为 8 moderate、0 high/critical,lint 两项既有 warning。JS 919926/gzip267601、CSS116185/gzip23035 字节,未放宽预算。
- 独立只读代码审查未发现问题。本地浏览器核对中英订阅和隐私文案,390×844 英文订阅无横向溢出;本地邮件关闭,不代表真实收件或生产 DOM。CI 与部署凭据完成后另行追加。
- 未修改 DNS、Sites 环境、D1 schema、任务、生产邮件开关或额度;不调用真实发信或投递队列。测试与真实收件验收分开记录。
4 changes: 3 additions & 1 deletion docs/operations/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
| owner 身份、后台、MCP、采编任务 | [Owner 管理](owner-management.md) | 现有 Sites 项目的所有者访问及受信任连接 |
| GitHub、构建、Sites 发布、D1、回滚 | [部署实施维护](deployment-maintenance.md) | GitHub PR/合并权;现有 Sites 项目的源码、版本及部署权 |

2026-10-14 [收件人级跟踪退出迭代](../iterations/2026-10-14-brevo-tracking-consent.md) 记录统一 API 参数、账户侧前置条件及真实邮件验证边界。

## 当前主线与证据

2026-10-13 **v1.0.1 标签已推送、正式站点已更新为 Sites v17**;发布提交 `fae53ff09c26ca10985e5a48d04a76fc1511046b`,部署 13:48:23 UTC 成功,119 项 CI 与原构建预算通过。首次本地 HTTP 失败及同提交重跑成功均保留。最新完成状态、源码、tag 和 Sites 映射见 [v1.0.1 回执](../releases/v1.0.1.md) 与 [CURRENT_STATE.json](../CURRENT_STATE.json) 的 `release`。以下 v1.0.0 项保留为历史证据,不作为最新运行版本;当前发布不新增真实收件验收或改变邮件额度。
Expand Down Expand Up @@ -42,7 +44,7 @@
## 尚需后续验证

- 8 项 moderate 依赖问题与 v1.0.1 JS 原始体积仅 39 字节余量(919961 / 920000):未来依赖/页面修改重新审计和构建,不降门槛。旧 CI 修复的 1169 字节余量仅属于历史构建。
- 邮件匿名跟踪已按交接接受并披露;完全关闭像素与链接改写尚未验证。中国大陆可访问性不保证。
- 邮件当前明确请求关闭打开/点击跟踪;账户侧功能状态及最终像素/链接改写移除仍待核验。中国大陆可访问性不保证。
- 当前账户权限、完整 DNS 清单、DKIM selector、实际部署版本、迁移 ledger、托管 D1 备份/恢复方式、实时任务状态与 provider 剩余额度均需在授权的生产维护中刷新。
- 真实 queued cancellation 与完整退信场景未全部观察;本地测试和历史验收不能扩写为所有生产情形都已验收。

Expand Down
Loading
Loading