chore(legal): one place for the operator's name and contact channels (placeholders)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N4f2nya58RoRu4yEmJgRGE
This commit is contained in:
Jesse_Chen
2026-09-30 09:42:04 +08:00
co-authored by Claude Opus 5.5
parent f898df5505
commit 788a84a4c0
+34
View File
@@ -0,0 +1,34 @@
/**
* Who runs Jyotisha and how users reach them (2026-09-30, compliance round).
*
* One place for the operator's legal name, address and contact channels, read
* by the user agreement, the privacy policy, the account-deletion notice and
* the feedback entry. The product owner will supply the real values; until
* then they are loud placeholders, and `legalEntityPlaceholders()` lets the
* production release checks refuse to ship them.
*/
export const LEGAL_ENTITY = {
/** 运营主体全称(公司或个体工商户),用于协议与隐私政策的「我们」。 */
operatorName: "【待填写:运营主体全称】",
/** 注册地址或联系地址。 */
address: "【待填写:联系地址】",
/** 用户与监管联系的邮箱(客服、投诉、个人信息请求)。 */
contactEmail: "【待填写:客服邮箱】",
/** 可选:客服电话或微信;为空则不显示。 */
contactPhone: "",
/** ICP 备案号;为空则页脚不显示。 */
icpNumber: "",
/** 协议与隐私政策文本版本;律师审定后改为正式版本号。 */
legalDocumentsVersion: "2026-09-30-draft",
/** 文本是否仍是草稿(未经律师审定)。页面顶部据此显示「草稿」标识。 */
legalDocumentsDraft: true,
} as const;
const PLACEHOLDER = /【待填写/;
/** Field names still holding a placeholder; empty when every required value is real. */
export function legalEntityPlaceholders(entity: Readonly<Record<string, unknown>> = LEGAL_ENTITY): string[] {
return Object.entries(entity)
.filter(([, value]) => typeof value === "string" && PLACEHOLDER.test(value))
.map(([key]) => key);
}