@agenticprimitives/contracts 1.0.0-alpha.16 → 1.0.0-alpha.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,37 +1,39 @@
1
1
  {
2
- "agentAccountFactory": "0xE5d2d68b510cC2325fAB5e278855F10DcF02B80A",
3
- "agentAccountImplementation": "0x3C547Ad14CcB3af20b86D671B0B04E61294ad05F",
4
- "agentNameRegistry": "0xD9a1eCe15F4265c2f367ccD7Df740baeDc3d0523",
5
- "agentNameResolver": "0x6E749688a49C3e32B59A54d374D2C116c4Bcc2ea",
6
- "agentNameUniversalResolver": "0xCbb8C3E3a0C87962dC4831152c936Ca2A8B7826b",
7
- "agentProfileResolver": "0x821de228dF591089575D9186BF9b5E305f12A221",
8
- "agentRelationship": "0x1c6D59DD6fd9C7AF39B5afD06FFE7FC032E3608e",
9
- "agreementRegistry": "0x92c4C46619842A8DDC5F59191d5FDb2c0aFc6874",
10
- "allowedMethodsEnforcer": "0xb6fa9a218F4d6d3Af3dDaE26E3639a98632d4C09",
11
- "allowedTargetsEnforcer": "0xca53c91257f6Fa2d1Bc51411B8da40056c861965",
12
- "approvedHashRegistry": "0x97e322FCDc233Ef4f8f81979D6e12bCdEF226eF0",
13
- "attestationRegistry": "0x34eF353F7DCdad386b7DD8643248A00bFcE863b8",
14
- "callDataHashEnforcer": "0x5d8e57091d716A3623c29Bd6CD07A502484dA845",
2
+ "agentAccountFactory": "0xA9B6e53FcD8DA3658DeD09f4e37b22baA25De715",
3
+ "agentAccountImplementation": "0x97DAC0cC056093B7DBFb4183804EA72f8d89972F",
4
+ "agentNameRegistry": "0x6629Cca40B008C0984a1Ca266Ca10A344420cac3",
5
+ "agentNameResolver": "0xA15B0703716DC8634B74F97723618f74Af3AaA73",
6
+ "agentNameUniversalResolver": "0xB890060dE1B3Fd2C78e1f0859da3883743eAD452",
7
+ "agentProfileResolver": "0xfcd37F8dca26ead889922b22C169c21370bd352a",
8
+ "agentRelationship": "0x0AF2455e3f76594E81d9042aD5FE22A5A35dc57f",
9
+ "agreementRegistry": "0xa62c888595Cd3A645e340EA7768B53b4fC257DF5",
10
+ "allowedMethodsEnforcer": "0xa076b759D6785bA5E67016e399Af651fC2ABC811",
11
+ "allowedTargetsEnforcer": "0xb06252FaD1D41B9943c73ec696Af70F268581625",
12
+ "approvedHashRegistry": "0x465f8DCE65aB51A1562CC60E6bc046ca8734D537",
13
+ "attestationRegistry": "0xD57f2e52395b9C99fAE8Abf823578faFe038f5B7",
14
+ "callDataHashEnforcer": "0xA614d6E5ECebc308b4e0bABDC7c832da059bb132",
15
15
  "chainId": 84532,
16
- "custodyPolicy": "0x7d94B5DAc5d66d30e9D2Ed401BbAB237e86804E6",
17
- "delegationManager": "0xd494a868B3216A307e9eCAe542D3903e3e364377",
16
+ "custodyPolicy": "0x5DB542eeBa652372afE6B4b0Cd40D999e65846de",
17
+ "delegationManager": "0x9eD1dC0FD2284fcd4967beeF3317129fee7a92e5",
18
18
  "deployer": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44",
19
- "entryPoint": "0x9B766cc05BD2193B5bE5dE50DB23DdB5F0B79c00",
20
- "geoFeatureRegistry": "0x903c289a091CC9200811202De7dF3C22B18325d6",
21
- "mockUsdc": "0xac4bf60DC027F71e70e7A821df64549e46d72Ed8",
22
- "ontologyTermRegistry": "0x701F8a8521Dfa814d042781C42fA5e88fbf88F86",
23
- "paymentEnforcer": "0x4680bcFBB2c2DC40254365300b922659919e3508",
24
- "paymentReceiptRegistry": "0x496f9B025BB3FBcE8CDB6375176dd30B2eCE5D73",
25
- "permissionlessSubregistry": "0xB4eF2166CEAccF8b2bbeAC9d0e28f991eb012385",
26
- "permissionlessSubregistryDemoAgent": "0x857Bec62Dc039A9D06602335d060886206fC0972",
27
- "quorumEnforcer": "0x38ffeA6A7c332a841E5fb33ED71B0BBF3387aFE1",
28
- "relationshipTypeRegistry": "0x6E6ec3d0fDA798c86D324F2681ad6E16a7435658",
29
- "shapeRegistry": "0xe105C57D384a62a3D465Ad6Ca2401B7117bC3415",
30
- "skillDefinitionRegistry": "0xA00622b30a1cCe201C27A7a9c9dAAe1349492457",
31
- "smartAgentPaymaster": "0xf40792F5b4d56931B9f77b4ae356fA89eA526224",
32
- "timestampEnforcer": "0x579e5cDDd94C27688CA5A0DDd2256995e7759280",
33
- "universalSignatureValidator": "0x01EC03058e98D0E56509E63b20F8454Fc31681F2",
34
- "valueEnforcer": "0x8cC88ac64F3A4C5784E7F8B41cAd8E17Ea05c34B",
35
- "agentRegistryBase": "0x1f8609F11fcaf0666534579EABe8B39778DFEdaA",
36
- "paymentEscrow": "0xF523F7a30b22F35B2Ee506392cfA16BD8FEEe411"
19
+ "entryPoint": "0x96E37dD695840AF7781E669bdca9d79E4d7d8040",
20
+ "geoFeatureRegistry": "0x7D4F6F5cca1cDb1c72b25c50aB80Fb9629BA800B",
21
+ "mockUsdc": "0x6cfF706bA1461a9ef9F5aaf8f1581301805FbF92",
22
+ "ontologyTermRegistry": "0xC03a64e1492021fEc27f31F066f09Abe28F73e00",
23
+ "paymentEnforcer": "0x4DAc5F8891112D0C34d207FcE5ED78f13cD2b7d8",
24
+ "paymentReceiptRegistry": "0xF659091DDB30D3A608d6f96fAEDB41e966B72433",
25
+ "permissionlessSubregistry": "0x598C7bbAf25f5246BE3D5A75FdEDC180D67D8026",
26
+ "permissionlessSubregistryDemoAgent": "0x571f9F2e12939F2fEDFC431aD6d7323d7483e02B",
27
+ "quorumEnforcer": "0xA4b148EfF1Ff1c116849F6e9D9c0059bC644873F",
28
+ "relationshipTypeRegistry": "0x8991a3ECf1DD41064Aa48DaF15a24B3d6a2811C5",
29
+ "shapeRegistry": "0xdE375012B37820C23272e2A2c9de2A8F6328aFA3",
30
+ "skillDefinitionRegistry": "0x167c8a31d5Fc36558A4eAD0CA96AcA7936a8e5e7",
31
+ "smartAgentPaymaster": "0x3444160e79C463B8F1e10f86Eae4047E22256aD0",
32
+ "timestampEnforcer": "0xBb8fF9c82417189c6EfeBbB369e9dd9d651aa0f3",
33
+ "universalSignatureValidator": "0x3bc65655d4b6fb57731A256fcd47Db2F8Fe36907",
34
+ "valueEnforcer": "0x3D2abD6c7C1319f2bbA96B3b76A7e0d92C620A39",
35
+ "agentRegistryBase": "0xB18534CA9c679968132ca2a43E454f5fA341030D",
36
+ "agenticGovernance": "0x27c1F21ffA275e61Fe152Edd4f2676fD6a816dDa",
37
+ "timelockController": "0xeB66E0B92287E53BB5A80bD2a01002150249DC94",
38
+ "governanceGuardian": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44"
37
39
  }
@@ -454,6 +454,25 @@
454
454
  ],
455
455
  "stateMutability": "view"
456
456
  },
457
+ {
458
+ "type": "function",
459
+ "name": "getPasskeyRpIdHash",
460
+ "inputs": [
461
+ {
462
+ "name": "credentialIdDigest",
463
+ "type": "bytes32",
464
+ "internalType": "bytes32"
465
+ }
466
+ ],
467
+ "outputs": [
468
+ {
469
+ "name": "",
470
+ "type": "bytes32",
471
+ "internalType": "bytes32"
472
+ }
473
+ ],
474
+ "stateMutability": "view"
475
+ },
457
476
  {
458
477
  "type": "function",
459
478
  "name": "hasAcceptedSessionDelegation",
@@ -697,7 +716,7 @@
697
716
  "internalType": "address"
698
717
  }
699
718
  ],
700
- "stateMutability": "pure"
719
+ "stateMutability": "view"
701
720
  },
702
721
  {
703
722
  "type": "function",
@@ -1150,24 +1169,6 @@
1150
1169
  "type": "bytes32",
1151
1170
  "indexed": true,
1152
1171
  "internalType": "bytes32"
1153
- },
1154
- {
1155
- "name": "x",
1156
- "type": "uint256",
1157
- "indexed": false,
1158
- "internalType": "uint256"
1159
- },
1160
- {
1161
- "name": "y",
1162
- "type": "uint256",
1163
- "indexed": false,
1164
- "internalType": "uint256"
1165
- },
1166
- {
1167
- "name": "rpIdHash",
1168
- "type": "bytes32",
1169
- "indexed": false,
1170
- "internalType": "bytes32"
1171
1172
  }
1172
1173
  ],
1173
1174
  "anonymous": false
@@ -53,6 +53,19 @@
53
53
  ],
54
54
  "stateMutability": "view"
55
55
  },
56
+ {
57
+ "type": "function",
58
+ "name": "SELF_PASSKEY_TRUSTEE",
59
+ "inputs": [],
60
+ "outputs": [
61
+ {
62
+ "name": "",
63
+ "type": "address",
64
+ "internalType": "address"
65
+ }
66
+ ],
67
+ "stateMutability": "view"
68
+ },
56
69
  {
57
70
  "type": "function",
58
71
  "name": "accountImplementation",
@@ -443,6 +456,11 @@
443
456
  "name": "NotGovernance",
444
457
  "inputs": []
445
458
  },
459
+ {
460
+ "type": "error",
461
+ "name": "SelfPasskeyTrusteeWithoutPasskey",
462
+ "inputs": []
463
+ },
446
464
  {
447
465
  "type": "error",
448
466
  "name": "SystemPaused",
@@ -580,10 +580,10 @@
580
580
  "internalType": "address"
581
581
  },
582
582
  {
583
- "name": "guardian",
584
- "type": "address",
583
+ "name": "guardianCommitment",
584
+ "type": "bytes32",
585
585
  "indexed": true,
586
- "internalType": "address"
586
+ "internalType": "bytes32"
587
587
  }
588
588
  ],
589
589
  "anonymous": false
@@ -599,10 +599,10 @@
599
599
  "internalType": "address"
600
600
  },
601
601
  {
602
- "name": "guardian",
603
- "type": "address",
602
+ "name": "guardianCommitment",
603
+ "type": "bytes32",
604
604
  "indexed": true,
605
- "internalType": "address"
605
+ "internalType": "bytes32"
606
606
  }
607
607
  ],
608
608
  "anonymous": false
@@ -35,8 +35,11 @@ export interface Deployments {
35
35
  readonly "universalSignatureValidator": Address;
36
36
  readonly "valueEnforcer": Address;
37
37
  readonly "agentRegistryBase": Address;
38
- readonly "paymentEscrow": Address;
38
+ readonly "agenticGovernance": Address;
39
+ readonly "timelockController": Address;
40
+ readonly "governanceGuardian": Address;
39
41
  readonly "chainId": number;
42
+ readonly "deploymentEpoch": string;
40
43
  }
41
44
  export declare const CONTRACTS: Deployments;
42
45
  export default CONTRACTS;
@@ -1,40 +1,43 @@
1
1
  // Generated by scripts/build-deployments.mjs — do not edit by hand.
2
2
  // Source: deployments-base-sepolia.json
3
3
  export const CONTRACTS = {
4
- "agentAccountFactory": "0xE5d2d68b510cC2325fAB5e278855F10DcF02B80A",
5
- "agentAccountImplementation": "0x3C547Ad14CcB3af20b86D671B0B04E61294ad05F",
6
- "agentNameRegistry": "0xD9a1eCe15F4265c2f367ccD7Df740baeDc3d0523",
7
- "agentNameResolver": "0x6E749688a49C3e32B59A54d374D2C116c4Bcc2ea",
8
- "agentNameUniversalResolver": "0xCbb8C3E3a0C87962dC4831152c936Ca2A8B7826b",
9
- "agentProfileResolver": "0x821de228dF591089575D9186BF9b5E305f12A221",
10
- "agentRelationship": "0x1c6D59DD6fd9C7AF39B5afD06FFE7FC032E3608e",
11
- "agreementRegistry": "0x92c4C46619842A8DDC5F59191d5FDb2c0aFc6874",
12
- "allowedMethodsEnforcer": "0xb6fa9a218F4d6d3Af3dDaE26E3639a98632d4C09",
13
- "allowedTargetsEnforcer": "0xca53c91257f6Fa2d1Bc51411B8da40056c861965",
14
- "approvedHashRegistry": "0x97e322FCDc233Ef4f8f81979D6e12bCdEF226eF0",
15
- "attestationRegistry": "0x34eF353F7DCdad386b7DD8643248A00bFcE863b8",
16
- "callDataHashEnforcer": "0x5d8e57091d716A3623c29Bd6CD07A502484dA845",
4
+ "agentAccountFactory": "0xA9B6e53FcD8DA3658DeD09f4e37b22baA25De715",
5
+ "agentAccountImplementation": "0x97DAC0cC056093B7DBFb4183804EA72f8d89972F",
6
+ "agentNameRegistry": "0x6629Cca40B008C0984a1Ca266Ca10A344420cac3",
7
+ "agentNameResolver": "0xA15B0703716DC8634B74F97723618f74Af3AaA73",
8
+ "agentNameUniversalResolver": "0xB890060dE1B3Fd2C78e1f0859da3883743eAD452",
9
+ "agentProfileResolver": "0xfcd37F8dca26ead889922b22C169c21370bd352a",
10
+ "agentRelationship": "0x0AF2455e3f76594E81d9042aD5FE22A5A35dc57f",
11
+ "agreementRegistry": "0xa62c888595Cd3A645e340EA7768B53b4fC257DF5",
12
+ "allowedMethodsEnforcer": "0xa076b759D6785bA5E67016e399Af651fC2ABC811",
13
+ "allowedTargetsEnforcer": "0xb06252FaD1D41B9943c73ec696Af70F268581625",
14
+ "approvedHashRegistry": "0x465f8DCE65aB51A1562CC60E6bc046ca8734D537",
15
+ "attestationRegistry": "0xD57f2e52395b9C99fAE8Abf823578faFe038f5B7",
16
+ "callDataHashEnforcer": "0xA614d6E5ECebc308b4e0bABDC7c832da059bb132",
17
17
  "chainId": 84532,
18
- "custodyPolicy": "0x7d94B5DAc5d66d30e9D2Ed401BbAB237e86804E6",
19
- "delegationManager": "0xd494a868B3216A307e9eCAe542D3903e3e364377",
18
+ "custodyPolicy": "0x5DB542eeBa652372afE6B4b0Cd40D999e65846de",
19
+ "delegationManager": "0x9eD1dC0FD2284fcd4967beeF3317129fee7a92e5",
20
20
  "deployer": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44",
21
- "entryPoint": "0x9B766cc05BD2193B5bE5dE50DB23DdB5F0B79c00",
22
- "geoFeatureRegistry": "0x903c289a091CC9200811202De7dF3C22B18325d6",
23
- "mockUsdc": "0xac4bf60DC027F71e70e7A821df64549e46d72Ed8",
24
- "ontologyTermRegistry": "0x701F8a8521Dfa814d042781C42fA5e88fbf88F86",
25
- "paymentEnforcer": "0x4680bcFBB2c2DC40254365300b922659919e3508",
26
- "paymentReceiptRegistry": "0x496f9B025BB3FBcE8CDB6375176dd30B2eCE5D73",
27
- "permissionlessSubregistry": "0xB4eF2166CEAccF8b2bbeAC9d0e28f991eb012385",
28
- "permissionlessSubregistryDemoAgent": "0x857Bec62Dc039A9D06602335d060886206fC0972",
29
- "quorumEnforcer": "0x38ffeA6A7c332a841E5fb33ED71B0BBF3387aFE1",
30
- "relationshipTypeRegistry": "0x6E6ec3d0fDA798c86D324F2681ad6E16a7435658",
31
- "shapeRegistry": "0xe105C57D384a62a3D465Ad6Ca2401B7117bC3415",
32
- "skillDefinitionRegistry": "0xA00622b30a1cCe201C27A7a9c9dAAe1349492457",
33
- "smartAgentPaymaster": "0xf40792F5b4d56931B9f77b4ae356fA89eA526224",
34
- "timestampEnforcer": "0x579e5cDDd94C27688CA5A0DDd2256995e7759280",
35
- "universalSignatureValidator": "0x01EC03058e98D0E56509E63b20F8454Fc31681F2",
36
- "valueEnforcer": "0x8cC88ac64F3A4C5784E7F8B41cAd8E17Ea05c34B",
37
- "agentRegistryBase": "0x1f8609F11fcaf0666534579EABe8B39778DFEdaA",
38
- "paymentEscrow": "0xF523F7a30b22F35B2Ee506392cfA16BD8FEEe411"
21
+ "entryPoint": "0x96E37dD695840AF7781E669bdca9d79E4d7d8040",
22
+ "geoFeatureRegistry": "0x7D4F6F5cca1cDb1c72b25c50aB80Fb9629BA800B",
23
+ "mockUsdc": "0x6cfF706bA1461a9ef9F5aaf8f1581301805FbF92",
24
+ "ontologyTermRegistry": "0xC03a64e1492021fEc27f31F066f09Abe28F73e00",
25
+ "paymentEnforcer": "0x4DAc5F8891112D0C34d207FcE5ED78f13cD2b7d8",
26
+ "paymentReceiptRegistry": "0xF659091DDB30D3A608d6f96fAEDB41e966B72433",
27
+ "permissionlessSubregistry": "0x598C7bbAf25f5246BE3D5A75FdEDC180D67D8026",
28
+ "permissionlessSubregistryDemoAgent": "0x571f9F2e12939F2fEDFC431aD6d7323d7483e02B",
29
+ "quorumEnforcer": "0xA4b148EfF1Ff1c116849F6e9D9c0059bC644873F",
30
+ "relationshipTypeRegistry": "0x8991a3ECf1DD41064Aa48DaF15a24B3d6a2811C5",
31
+ "shapeRegistry": "0xdE375012B37820C23272e2A2c9de2A8F6328aFA3",
32
+ "skillDefinitionRegistry": "0x167c8a31d5Fc36558A4eAD0CA96AcA7936a8e5e7",
33
+ "smartAgentPaymaster": "0x3444160e79C463B8F1e10f86Eae4047E22256aD0",
34
+ "timestampEnforcer": "0xBb8fF9c82417189c6EfeBbB369e9dd9d651aa0f3",
35
+ "universalSignatureValidator": "0x3bc65655d4b6fb57731A256fcd47Db2F8Fe36907",
36
+ "valueEnforcer": "0x3D2abD6c7C1319f2bbA96B3b76A7e0d92C620A39",
37
+ "agentRegistryBase": "0xB18534CA9c679968132ca2a43E454f5fA341030D",
38
+ "agenticGovernance": "0x27c1F21ffA275e61Fe152Edd4f2676fD6a816dDa",
39
+ "timelockController": "0xeB66E0B92287E53BB5A80bD2a01002150249DC94",
40
+ "governanceGuardian": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44",
41
+ "deploymentEpoch": "ep_015f71625117a4d1"
39
42
  };
40
43
  export default CONTRACTS;
@@ -4,6 +4,7 @@ import type { Address } from 'viem';
4
4
  export interface Deployments {
5
5
  readonly "agreementRegistry": Address;
6
6
  readonly "attestationRegistry": Address;
7
+ readonly "deploymentEpoch": string;
7
8
  }
8
9
  export declare const CONTRACTS: Deployments;
9
10
  export default CONTRACTS;
@@ -2,6 +2,7 @@
2
2
  // Source: deployments-registries-base-sepolia.json
3
3
  export const CONTRACTS = {
4
4
  "agreementRegistry": "0x9f2A085f0bd2d8Afb69490C0C98D88592093906A",
5
- "attestationRegistry": "0x4a156CAaE69E894E3C5e6F3064fE028F138b6847"
5
+ "attestationRegistry": "0x4a156CAaE69E894E3C5e6F3064fE028F138b6847",
6
+ "deploymentEpoch": "ep_45ca31c3315a5978"
6
7
  };
7
8
  export default CONTRACTS;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agenticprimitives/contracts",
3
- "version": "1.0.0-alpha.16",
3
+ "version": "1.0.0-alpha.18",
4
4
  "description": "Solidity contracts + ABIs + flattened sources + per-network deployment addresses for the agenticprimitives stack.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -441,7 +441,7 @@ contract AgentAccount is
441
441
  $.piaToCredentialId[pia] = credIdDigest;
442
442
  $.rpIdHashOf[credIdDigest] = rpIdHash;
443
443
  $.count = 1;
444
- emit PasskeyAdded(credIdDigest, x, y, rpIdHash);
444
+ emit PasskeyAdded(credIdDigest);
445
445
  emit CustodianAdded(pia);
446
446
  }
447
447
 
@@ -1515,15 +1515,23 @@ contract AgentAccount is
1515
1515
  }
1516
1516
 
1517
1517
  /// @notice Deterministically derive the Passkey-Identity-Address for
1518
- /// a P-256 public key. Exposed as `pure` so off-chain code +
1519
- /// other contracts (CustodyPolicy, factory) can recompute it
1520
- /// without reading account state.
1521
- function passkeyIdentity(uint256 x, uint256 y) public pure returns (address) {
1518
+ /// a P-256 public key ON THIS ACCOUNT. Spec 302 W2: the PIA is
1519
+ /// account-scoped — `keccak256(abi.encode(x, y, address(this)))` —
1520
+ /// so the same physical passkey yields a DIFFERENT custodian
1521
+ /// address on every account it custodies. The pre-302 global
1522
+ /// derivation (`keccak256(abi.encode(x, y))`) made the PIA a
1523
+ /// public cross-account join key: one `CustodianAdded(pia)` log
1524
+ /// scan clustered a person's SA with every org/treasury SA their
1525
+ /// root passkey controls. Off-chain mirror: account-custody
1526
+ /// `passkeyIdentity(x, y, account)`; the v=2 signature slot
1527
+ /// verifier (SignatureSlotRecovery) re-derives with the same
1528
+ /// account scope.
1529
+ function passkeyIdentity(uint256 x, uint256 y) public view returns (address) {
1522
1530
  return _passkeyIdentity(x, y);
1523
1531
  }
1524
1532
 
1525
- function _passkeyIdentity(uint256 x, uint256 y) internal pure returns (address) {
1526
- return address(uint160(uint256(keccak256(abi.encode(x, y)))));
1533
+ function _passkeyIdentity(uint256 x, uint256 y) internal view returns (address) {
1534
+ return address(uint160(uint256(keccak256(abi.encode(x, y, address(this))))));
1527
1535
  }
1528
1536
 
1529
1537
  /// @inheritdoc IAgentAccount
@@ -1622,7 +1630,14 @@ contract AgentAccount is
1622
1630
  assembly { $.slot := slot }
1623
1631
  }
1624
1632
 
1625
- event PasskeyAdded(bytes32 indexed credentialIdDigest, uint256 x, uint256 y, bytes32 rpIdHash);
1633
+ /// @dev Spec 302 W1 — the event carries ONLY the credential digest. The raw
1634
+ /// P256 coordinates and rpIdHash were removed: identical (x, y) across
1635
+ /// accounts let any log indexer cluster every SA one physical passkey
1636
+ /// custodies (publicly defeating ADR-0025's person↔org privacy), and
1637
+ /// sha256(rpId) is a guessable-preimage domain disclosure. Coordinates
1638
+ /// remain in storage — the ONE read path is `getPasskey(credentialIdDigest)`
1639
+ /// (ADR-0012/0013; INV-302-3).
1640
+ event PasskeyAdded(bytes32 indexed credentialIdDigest);
1626
1641
  event PasskeyRemoved(bytes32 indexed credentialIdDigest);
1627
1642
 
1628
1643
  /// @notice Register a new WebAuthn credential bound to a specific RP.
@@ -1658,7 +1673,7 @@ contract AgentAccount is
1658
1673
  $.piaToCredentialId[pia] = credentialIdDigest;
1659
1674
  $.rpIdHashOf[credentialIdDigest] = rpIdHash;
1660
1675
  $.count += 1;
1661
- emit PasskeyAdded(credentialIdDigest, x, y, rpIdHash);
1676
+ emit PasskeyAdded(credentialIdDigest);
1662
1677
  emit CustodianAdded(pia);
1663
1678
  }
1664
1679
 
@@ -1693,6 +1708,14 @@ contract AgentAccount is
1693
1708
  return (k.x, k.y);
1694
1709
  }
1695
1710
 
1711
+ /// @notice Read the RP-ID hash a credential was registered against.
1712
+ /// @dev Spec 302 W1 (INV-302-3): the slimmed `PasskeyAdded` event no longer
1713
+ /// carries `rpIdHash`; this getter is the ONE read path for it
1714
+ /// (ADR-0012/0013 — `readContract`, no log walking).
1715
+ function getPasskeyRpIdHash(bytes32 credentialIdDigest) external view returns (bytes32) {
1716
+ return _passkeyStorage().rpIdHashOf[credentialIdDigest];
1717
+ }
1718
+
1696
1719
  /// @notice Total count of registered passkeys.
1697
1720
  function passkeyCount() external view returns (uint256) {
1698
1721
  return _passkeyStorage().count;
@@ -101,6 +101,25 @@ contract AgentAccountFactory is GovernanceManaged {
101
101
  /// threshold at `_buildValidatorInitData:252`.
102
102
  uint256 public constant MAX_INITIAL_CUSTODIANS = 32;
103
103
 
104
+ /// @notice Spec 302 W2 — trustee-slot sentinel meaning "the initial
105
+ /// passkey's Passkey-Identity-Address on the account being
106
+ /// deployed". The PIA is now account-scoped, so it CANNOT be
107
+ /// computed before the CREATE2 address exists — but the salt
108
+ /// commits to `params.trustees` (CA-F1). Clients that want the
109
+ /// initial passkey to be its own recovery trustee (mode>0
110
+ /// self-recovery bootstrap) pass this sentinel; the factory
111
+ /// resolves it to the real per-account PIA AFTER the deploy,
112
+ /// when it builds the CustodyPolicy install blob. The address
113
+ /// therefore commits to the INTENT ("self-passkey is a
114
+ /// trustee"), which is deterministic, instead of the derived
115
+ /// value, which is circular.
116
+ address public constant SELF_PASSKEY_TRUSTEE =
117
+ address(uint160(uint256(keccak256("ap.trustee.self-initial-passkey"))));
118
+
119
+ /// @notice Spec 302 W2 — `SELF_PASSKEY_TRUSTEE` passed without an
120
+ /// initial passkey to resolve it to.
121
+ error SelfPasskeyTrusteeWithoutPasskey();
122
+
104
123
  constructor(
105
124
  IEntryPoint entryPoint_,
106
125
  address delegationManager_,
@@ -176,7 +195,7 @@ contract AgentAccountFactory is GovernanceManaged {
176
195
  account = AgentAccount(payable(address(proxy)));
177
196
 
178
197
  if (params.mode > 0) {
179
- bytes memory validatorInit = _buildValidatorInitData(params, timelockOverrides);
198
+ bytes memory validatorInit = _buildValidatorInitData(params, timelockOverrides, address(account));
180
199
  account.installModule(2 /* MODULE_TYPE_EXECUTOR */, custodyPolicy, validatorInit);
181
200
  }
182
201
 
@@ -281,6 +300,15 @@ contract AgentAccountFactory is GovernanceManaged {
281
300
  revert TooManyInitialCustodians(params.custodians.length, MAX_INITIAL_CUSTODIANS);
282
301
  }
283
302
 
303
+ // Spec 302 W2 — the self-passkey trustee sentinel is meaningless
304
+ // without an initial passkey to resolve it to (fail-closed at
305
+ // predict time too, so counterfactual and deploy agree).
306
+ bool hasSentinel;
307
+ for (uint256 i; i < params.trustees.length; i++) {
308
+ if (params.trustees[i] == SELF_PASSKEY_TRUSTEE) { hasSentinel = true; break; }
309
+ }
310
+ if (hasSentinel && !hasPasskey) revert SelfPasskeyTrusteeWithoutPasskey();
311
+
284
312
  if (params.mode == 0) return;
285
313
 
286
314
  uint256 nTrustees = params.trustees.length;
@@ -305,7 +333,8 @@ contract AgentAccountFactory is GovernanceManaged {
305
333
  /// external custodians + (1 if initial passkey, else 0).
306
334
  function _buildValidatorInitData(
307
335
  AgentAccountInitParams calldata params,
308
- uint32[7] calldata timelockOverrides
336
+ uint32[7] calldata timelockOverrides,
337
+ address account
309
338
  ) internal view returns (bytes memory) {
310
339
  uint256 nSigners = params.custodians.length;
311
340
  if (params.initialPasskeyX != 0 && params.initialPasskeyY != 0) nSigners++;
@@ -344,10 +373,21 @@ contract AgentAccountFactory is GovernanceManaged {
344
373
 
345
374
  uint8 recThr = uint8(params.trustees.length / 2 + 1);
346
375
 
376
+ // Spec 302 W2 — resolve the self-passkey trustee sentinel to the
377
+ // account-scoped PIA. Runs AFTER the deploy (the account address —
378
+ // and thus the per-account PIA — exists), while the CREATE2 salt
379
+ // committed to the sentinel form (deterministic pre-deploy).
380
+ address[] memory trustees = new address[](params.trustees.length);
381
+ for (uint256 i; i < trustees.length; i++) {
382
+ trustees[i] = params.trustees[i] == SELF_PASSKEY_TRUSTEE
383
+ ? AgentAccount(payable(account)).passkeyIdentity(params.initialPasskeyX, params.initialPasskeyY)
384
+ : params.trustees[i];
385
+ }
386
+
347
387
  return abi.encode(
348
388
  params.mode,
349
389
  recThr,
350
- params.trustees,
390
+ trustees,
351
391
  thresholds,
352
392
  timelocks,
353
393
  uint256(0.01 ether),
@@ -273,8 +273,17 @@ contract CustodyPolicy {
273
273
  event CustodyChangeScheduled(address indexed account, uint256 indexed changeId, CustodyAction indexed action, uint64 eta, address proposer);
274
274
  event CustodyChangeApplied(address indexed account, uint256 indexed changeId);
275
275
  event ScheduledChangeCancelled(address indexed account, uint256 indexed changeId);
276
- event GuardianAdded(address indexed account, address indexed guardian);
277
- event GuardianRemoved(address indexed account, address indexed guardian);
276
+ /// @dev Spec 302 W3 — guardian/trustee events carry an opaque MEMBERSHIP
277
+ /// COMMITMENT, not the raw guardian address: `GuardianAdded(account,
278
+ /// guardian)` published each person's social-recovery graph (who
279
+ /// guards whom) permanently. The commitment
280
+ /// `keccak256(abi.encode(guardian, account))` is unsalted +
281
+ /// on-chain-reproducible (ADR-0040 posture): anyone holding a
282
+ /// CANDIDATE guardian address can confirm membership, but nobody can
283
+ /// enumerate the graph from logs. The ONE read path for a live check
284
+ /// is `isTrustee(account, signer)` (ADR-0012/0013).
285
+ event GuardianAdded(address indexed account, bytes32 indexed guardianCommitment);
286
+ event GuardianRemoved(address indexed account, bytes32 indexed guardianCommitment);
278
287
  event ThresholdChanged(address indexed account, uint8 indexed tier, uint8 oldValue, uint8 newValue);
279
288
  event ModeChanged(address indexed account, uint8 oldMode, uint8 newMode);
280
289
  event T3CeilingChanged(address indexed account, uint256 oldCeiling, uint256 newCeiling);
@@ -753,7 +762,8 @@ contract CustodyPolicy {
753
762
  address prev;
754
763
  for (uint256 i; i < vargs.reqThreshold; i++) {
755
764
  address signer = SignatureSlotRecovery.recoverFromSlot(
756
- vargs.payloadHash, sigsMem, i, approvedHashReg
765
+ // Spec 302 W2 — v=2 passkey slots derive the per-ACCOUNT PIA.
766
+ vargs.payloadHash, sigsMem, i, approvedHashReg, account
757
767
  );
758
768
  if (signer <= prev) revert AdminDuplicateOrUnsortedSigner(signer);
759
769
  prev = signer;
@@ -871,7 +881,7 @@ contract CustodyPolicy {
871
881
  if (c.trustees[g]) revert TrusteeAlreadyExists(g);
872
882
  c.trustees[g] = true;
873
883
  c.trusteeCount += 1;
874
- emit GuardianAdded(account, g);
884
+ emit GuardianAdded(account, keccak256(abi.encode(g, account)));
875
885
  }
876
886
 
877
887
  function _applyRemoveGuardian(address account, Config storage c, address g) internal {
@@ -881,7 +891,7 @@ contract CustodyPolicy {
881
891
  }
882
892
  c.trustees[g] = false;
883
893
  c.trusteeCount -= 1;
884
- emit GuardianRemoved(account, g);
894
+ emit GuardianRemoved(account, keccak256(abi.encode(g, account)));
885
895
  }
886
896
 
887
897
  function _applyChangeMode(address account, Config storage c, uint8 newMode) internal {
@@ -179,7 +179,10 @@ contract QuorumEnforcer is ICaveatEnforcer {
179
179
  expectedPayloadHash,
180
180
  signatures,
181
181
  i,
182
- approvedHashRegistry
182
+ approvedHashRegistry,
183
+ // Spec 302 W2 — quorum passkey signers are custodians OF THE
184
+ // DELEGATOR account; their v=2 PIA is scoped to it.
185
+ delegator
183
186
  );
184
187
 
185
188
  // Sorted-ascending check (also rejects duplicates).
@@ -28,8 +28,10 @@ import {WebAuthnLib} from "./WebAuthnLib.sol";
28
28
  * v == 2 → WebAuthn passkey sig (agenticprimitives
29
29
  * extension; NOT in Safe). r holds the
30
30
  * Passkey-Identity-Address (PIA, derived
31
- * from the P-256 pubkey via
32
- * `address(uint160(uint256(keccak256(abi.encode(x, y)))))`).
31
+ * from the P-256 pubkey + the account it is
32
+ * scoped to via
33
+ * `address(uint160(uint256(keccak256(abi.encode(x, y, passkeyScope)))))`
34
+ * — per-account since spec 302 W2).
33
35
  * s holds the byte offset into `signatures`
34
36
  * to a length-prefixed tail containing
35
37
  * `abi.encode(uint256 x, uint256 y, bytes32 rpIdHash, WebAuthnLib.Assertion assertion)`.
@@ -77,12 +79,21 @@ library SignatureSlotRecovery {
77
79
  * caller does not want to allow v=1 sigs
78
80
  * (e.g. quorum-of-owners admin paths
79
81
  * that don't accept pre-approved hashes).
82
+ * @param passkeyScope Spec 302 W2 — the AgentAccount the v=2
83
+ * slot's PIA is scoped to (the account
84
+ * whose custody the passkey signer claims:
85
+ * CustodyPolicy passes `account`, the
86
+ * QuorumEnforcer passes the `delegator`).
87
+ * The per-account derivation
88
+ * `keccak256(abi.encode(x, y, scope))`
89
+ * kills the cross-account PIA join key.
80
90
  */
81
91
  function recoverFromSlot(
82
92
  bytes32 payloadHash,
83
93
  bytes memory signatures,
84
94
  uint256 index,
85
- address approvedHashRegistry
95
+ address approvedHashRegistry,
96
+ address passkeyScope
86
97
  ) internal view returns (address signer) {
87
98
  bytes32 r;
88
99
  bytes32 s;
@@ -171,7 +182,8 @@ library SignatureSlotRecovery {
171
182
  // WebAuthnLib.Assertion assertion).
172
183
  (uint256 pubX, uint256 pubY, bytes32 rpIdHash, WebAuthnLib.Assertion memory assertion) =
173
184
  abi.decode(dyn, (uint256, uint256, bytes32, WebAuthnLib.Assertion));
174
- address derived = address(uint160(uint256(keccak256(abi.encode(pubX, pubY)))));
185
+ // Spec 302 W2 — per-account PIA (mirrors AgentAccount._passkeyIdentity).
186
+ address derived = address(uint160(uint256(keccak256(abi.encode(pubX, pubY, passkeyScope)))));
175
187
  if (derived != signer) revert PasskeyPubKeyMismatch(signer, derived);
176
188
  // WA-2: require UV at the slot level. This path verifies custody-COUNCIL
177
189
  // passkey signatures (CustodyPolicy quorum: trustees/custodians authorizing
@@ -92,4 +92,10 @@ library AgentNamePredicates {
92
92
  bytes32 internal constant CONNECTION_KIND_YOUVERSION = keccak256("youversion");
93
93
  bytes32 internal constant CONNECTION_KIND_PASSKEY = keccak256("passkey");
94
94
  bytes32 internal constant CONNECTION_KIND_MULTI = keccak256("multi");
95
+ // Social/KMS-class kinds (specs 319/320) — per-subject C_sub custodians, code-flow sign-in.
96
+ // The attribute write path validates only the PREDICATE (OntologyTermRegistry.isActive), NOT the
97
+ // enum value, so these are publishable on the live deployment with no redeploy; the ShapeRegistry
98
+ // ConnectionKindEnum seed adds them for forward shape-validation correctness (Deploy.s.sol).
99
+ bytes32 internal constant CONNECTION_KIND_EMAIL = keccak256("email");
100
+ bytes32 internal constant CONNECTION_KIND_PHONE = keccak256("phone");
95
101
  }