跳转到内容

处理用户撤销 H2A 关系 / Grant

用户撤销了和 Agent 的 H2A 关系(或某个 Grant),Agent 必须立即清理本地存 的用户数据。GDPR / CCPA 合规底线。

代码

import { HasheeAgent } from "@hasheeai/agent-sdk-ts";
import { Pool } from "pg";
const db = new Pool({ connectionString: process.env.DATABASE_URL });
const agent = await HasheeAgent.init({
agentId: process.env.HASHEE_AGENT_ID!,
token: process.env.HASHEE_AGENT_TOKEN!,
baseUrl: "https://api.hashee.ai",
connectionMode: "websocket",
});
agent.addEventHandler(async (event) => {
if (event.type === "relation.revoked" || event.type === "relation.terminated") {
await handleRelationRevoked(event.payload);
}
if (event.type === "grant.revoked") {
await handleGrantRevoked(event.payload);
}
});
async function handleRelationRevoked(payload: any) {
const { user_id, conversation_id, reason } = payload;
console.log(`[revoke] user ${user_id} (reason: ${reason})`);
await db.query("BEGIN");
try {
// 1. 删该 user 的对话明文(如果业务侧存了)
await db.query("DELETE FROM cs_messages WHERE user_id = $1", [user_id]);
// 2. 删用户档案 / 个性化数据
await db.query("DELETE FROM user_profiles WHERE user_id = $1", [user_id]);
// 3. 删衍生数据(向量、embedding、AI 训练样本)
await db.query("DELETE FROM doc_chunks WHERE user_id = $1", [user_id]);
await db.query("DELETE FROM vote_choices WHERE user_id = $1", [user_id]);
// 4. 撤销外部资源(API key / subscription / 等)
// await externalApi.revokeUserAccess({ user_id });
// 5. 写本地审计日志(合规要求)
await db.query(
`INSERT INTO audit_log (action, user_id, agent_id, ts, details)
VALUES ('relation_revoked', $1, $2, NOW(), $3)`,
[user_id, process.env.HASHEE_AGENT_ID, JSON.stringify({ reason, conversation_id })],
);
await db.query("COMMIT");
} catch (e) {
await db.query("ROLLBACK");
throw e;
}
console.log(`[revoke] cleaned up data for ${user_id}`);
}
async function handleGrantRevoked(payload: any) {
const { grant_id, scope, user_id } = payload;
console.log(`[grant-revoke] grant ${grant_id} (${scope}) user ${user_id}`);
// 1. 删该 grant 的派生数据(如 grant 范围内的 cache)
await db.query("DELETE FROM grant_cache WHERE grant_id = $1", [grant_id]);
// 2. 内存 cache(如有)
myInMemoryCache.delete(grant_id);
// 3. 审计日志
await db.query(
`INSERT INTO audit_log (action, user_id, ts, details)
VALUES ('grant_revoked', $1, NOW(), $2)`,
[user_id, JSON.stringify({ grant_id, scope })],
);
}
console.log("[revoke-handler] up");

不要清理的(合规要求)

  • ✗ 平台的 grant_access_log(DB trigger 强制 append-only,平台保留)
  • ✗ Hashee 平台的 audit_records admin.* 行(同上)
  • ✗ 你自己的”事件审计日志”(如上 audit_log 表)— 这是你合规的证据, 反映了”用户撤销后我做了清理”,永不删

验证

事件触发后业务侧应能在日志里看到:

[revoke] user 01906abc-... (reason: user_initiated)
[revoke] cleaned up data for 01906abc-...

如果没看到 → 检查 addEventHandler 是否注册 + agent connection 是否 healthy。

测试

模拟撤销在 Hashee app 操作:

  1. 用真实账号 + 添加你 Agent
  2. 进会话 → 长按 → 删除 + 撤销授权
  3. 看你 Agent 进程日志应触发 cleanup

详细文档