# PolicyRegistry — 策略确权

## 设计意图

把 **AI 策略文本（OPA Rego DSL）的内容哈希**注册到链上，作为 Agent 行为合规性判定的不可变锚点。链上只存 hash + 元数据，Rego 全文存 IPFS / Arweave。

**确权语义**：

* **publisher**：第一个 register 该 policyHash 的地址，永久锁定
* **active**：当前 policy 是否启用
* **deactivate** ≠ delete：旧引用仍可查询，仅新 spec 不能 bind

## 接口

```solidity
interface IPolicyRegistry {
    struct Policy {
        bytes32 policyHash; // keccak256(rego_text)
        address publisher;
        uint64 registeredAt;
        bool active;
        string templateName; // e.g. "EU AI Act high-risk"
        string contentURI; // ipfs://Qm... or ar://...
    }
    
    function registerPolicy(
        bytes32 policyHash,
        string calldata templateName,
        string calldata contentURI
    ) external;
    
    function deactivatePolicy(bytes32 policyHash) external; // only publisher
    function reactivatePolicy(bytes32 policyHash) external; // only publisher
    
    function getPolicy(bytes32 policyHash) external view returns (Policy memory);
    function isRegistered(bytes32 policyHash) external view returns (bool); // true if exists AND active
    function getPublisher(bytes32 policyHash) external view returns (address);
}
```

## 确权流程

### 1. Publisher 注册 policy

```solidity
// 任何 EOA 都可以注册（permissionless）
bytes32 policyHash = keccak256(bytes(regoText));
PolicyRegistry.registerPolicy(
    policyHash,
    "EU AI Act high-risk system",
    "ipfs://QmEU_AI_ACT_HIGH_RISK_FULL_TEXT_HASH"
);
// emit PolicyRegistered(policyHash, msg.sender, block.timestamp)
```

**关键约束**：

* `policyHash` 全局唯一；重复 register 直接 revert
* `msg.sender` 自动成为 `publisher`，**永久不可改**
* 没有 admin 可以 override publisher（合约层面没这个能力）

### 2. PoBRegistry 绑定 policy

```solidity
// PoBRegistry.sol (admin-only setter)
function setPolicyHash(bytes32 newPolicyHash) external onlyAdmin {
    require(policyRegistry.isRegistered(newPolicyHash), "PolicyNotRegistered");
    bytes32 old = configuredPolicyHash;
    configuredPolicyHash = newPolicyHash;
    emit PolicyHashUpdated(old, newPolicyHash);
}

// 后续 submitBatchWithPolicy 强制 batch 引用此 policy
function submitBatchWithPolicy(Batch calldata b, bytes calldata sig) external {
    require(b.policyHash == configuredPolicyHash, "PolicyMismatch");
    submitBatch(b, sig);
}
```

### 3. Publisher 撤销

```solidity
// only publisher
PolicyRegistry.deactivatePolicy(policyHash);
// isRegistered() returns false
// 但 getPolicy() 仍可读历史
// 已 bound batch 仍 valid (history immutable)
```

## EU AI Act high-risk 模板（实际链上案例）

| 字段             | 值                                                                    |
| -------------- | -------------------------------------------------------------------- |
| `policyHash`   | `0xfc53fc5e88de7760db17d4f0e39289edebfb8bfe10d277dbef22e9e85bdd6732` |
| `templateName` | `"EU AI Act high-risk system"`                                       |
| `contentURI`   | `"ipfs://QmEU_AI_ACT_v1"` (PoC: 占位符)                                 |
| `publisher`    | `0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266` (anvil rich#0)          |
| 引用合约           | `PoBRegistry.configuredPolicyHash`                                   |
| 链上事实           | chain 391 真链 SDK e2e 三 case 全绿 (commit `1f1e29d`)                    |

策略全文（mock 版）：

```rego
# EU AI Act Article 9 — Risk Management System (PoC simplification)
package eu_ai_act_high_risk

import future.keywords.if
import future.keywords.in

default allow = false

# 高风险 AI 系统的 5 个核心要求
allow if {
    has_human_oversight
    has_risk_mitigation_doc
    has_audit_trail
    has_explanation
    not violates_prohibited_practice
}

has_human_oversight if input.event.metadata.human_in_loop == true
has_risk_mitigation_doc if input.spec.risk_doc_hash != ""
has_audit_trail if input.event.timestamp > 0
has_explanation if input.event.explanation_hash != ""

violates_prohibited_practice if {
    input.event.action_id in [
        "social_scoring",
        "real_time_biometric_id_in_public",
        "subliminal_manipulation"
    ]
}
```

## 攻击向量与缓解

| # | 攻击                                                       | 缓解                                              |
| - | -------------------------------------------------------- | ----------------------------------------------- |
| 1 | 攻击者 register 一个 fake "EU AI Act" policyHash 占用 namespace | Permissionless 注册 = consumer 选择信任的 publisher 地址 |
| 2 | Publisher 私钥泄漏 → 恶意 deactivate                           | publisher 私钥应 HSM；考虑 multisig publisher         |
| 3 | PoBRegistry.setPolicyHash 被 admin 错误指向 fake policy       | onlyAdmin + 主网必须 Timelock                       |
| 4 | IPFS contentURI 不可达 → 失去 audit 能力                        | 多 pinning + Arweave 备份                          |
| 5 | 监管法规更新 → policy 文本要变                                     | 不能改 hash；必须 register newPolicyHash + 治理流程切换     |

详细见 [Trust Assumptions](/security/trust-assumptions.md) §2.10。

## 与 BehaviorSpecRegistry 的关系

```
BehaviorSpec (描述"agent 应该怎么做")
   │
   │ 引用 policyHash
   ▼
PolicyRegistry (描述"什么策略约束这个 spec")
   │
   │ 引用 templateName / contentURI
   ▼
EU AI Act / NIST RMF / 中国生成式 AI 办法 (法律 / 标准文本)
```

详见 [BehaviorSpecRegistry 确权](/registries-que-quan/behavior-spec-registry.md) + [L2 OPA Policy Engine](/protocol-mechanics/policy-engine-opa.md)。

## SDK 示例

### TypeScript (viem)

```typescript
import { createWalletClient, http, keccak256, toBytes } from 'viem';
import { PolicyRegistryABI } from '@babydriver/sdk';

const client = createWalletClient({
    account: myAccount,
    chain: chain391,
    transport: http('https://rpc-testnet.axblade.io'),
});

const regoText = await fetch('ipfs://QmEU_AI_ACT_v1').then(r => r.text());
const policyHash = keccak256(toBytes(regoText));

const txHash = await client.writeContract({
    address: POLICY_REGISTRY_ADDRESS,
    abi: PolicyRegistryABI,
    functionName: 'registerPolicy',
    args: [policyHash, 'EU AI Act high-risk system', 'ipfs://QmEU_AI_ACT_v1'],
});

console.log(`Registered: ${policyHash}`);
console.log(`Tx: ${txHash}`);
```

完整端到端示例见 [Examples → Register Policy](/integration-jie-ru-fang-shi/examples/register-policy.md)。

## 已修真 bug

无（已通过 slither + immutable 优化扫描，commit `7a1c8b5` + `70fcce0`）。

## 主网前必须

1. PoBRegistry.setPolicyHash 接 24h Timelock
2. Publisher 改用 multisig（Gnosis Safe 2/3）
3. 增加 governance 流程：deprecate policy 需 community vote

## 相关

* [L2 OPA Policy Engine](/protocol-mechanics/policy-engine-opa.md) — Rego DSL 评估机制
* [BehaviorSpec Registry](/registries-que-quan/behavior-spec-registry.md) — 行为规范确权
* [所有权与轮换](/registries-que-quan/ownership-and-rotation.md) — publisher / admin 权限切换流程
* [EU AI Act 策略免责](/legal-and-disclaimers/eu-ai-act-policy-disclaimer.md) — 法律边界


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://yellowpaper.axblade.io/registries-que-quan/policy-registry.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
