@agenticprimitives/contracts 1.0.0-alpha.15 → 1.0.0-alpha.17

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": "0x1D3BF769B3991faA7847872cE05FA22beE2f07e5",
3
- "agentAccountImplementation": "0xd96eA06208140763256899727B22A1DF7A09387d",
4
- "agentNameRegistry": "0x4e5a6369C91B9093ad17bF0eAc8d344F1b41EdE0",
5
- "agentNameResolver": "0x776a5bADb7DBE238048542E0c91f7a86933C8986",
6
- "agentNameUniversalResolver": "0x8539fad5B148512775cD3712bb55F2fd5f1C85cB",
7
- "agentProfileResolver": "0x82dBC51a77A92A51b177FFE97181cD40aa1c24ab",
8
- "agentRegistryBase": "0x54f76a5faab995f194cc61c50eb5e272c8d85cf4",
9
- "agentRelationship": "0x763c164d8275F76A806721B423aaB5ad6cb4fEA1",
10
- "agreementRegistry": "0xaD300f03EdDf8F015D5583feC8D5F2D1BBC6f854",
11
- "allowedMethodsEnforcer": "0xa149A31F32789cDBfd5f0eed1CF92E7BCb91b549",
12
- "allowedTargetsEnforcer": "0xfb78589C8a9f464BD1e9A340BC809CEe7949b17c",
13
- "approvedHashRegistry": "0x7152282bB71692E7f73ff31DdB43f4a50818845b",
14
- "attestationRegistry": "0x9f9bCAF7b238b87c6d7897767c473b6f8C55C0a6",
15
- "callDataHashEnforcer": "0x0fCE11eC016bd4Bc3a60951FbE4e9Fe7087955b1",
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",
16
15
  "chainId": 84532,
17
- "custodyPolicy": "0xF408e54dA113Fe6b785615750c6Bab6F9008A9d9",
18
- "delegationManager": "0xaCdB7001dB8305c23703f6DB0EfB8B9BC1d75D62",
16
+ "custodyPolicy": "0x5DB542eeBa652372afE6B4b0Cd40D999e65846de",
17
+ "delegationManager": "0x9eD1dC0FD2284fcd4967beeF3317129fee7a92e5",
19
18
  "deployer": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44",
20
- "entryPoint": "0x9Eb5F84E8323aACD4AD61b4b980aDB23B15c2903",
21
- "geoFeatureRegistry": "0x74AEb56420a8630c611c36b3053780d90191f94d",
22
- "mockUsdc": "0x07190E7586a468E808D6bd58dC3CEdEC0b25B8E3",
23
- "ontologyTermRegistry": "0x69670d24AcE8C47a294231a1fdC4207642669a25",
24
- "paymentEnforcer": "0xF08946A2c4eed77f366AfDc39AE150F2262E5d29",
25
- "paymentEscrow": "0x30f0fd53dc1245062962b498be3a7e9641cc7c6c",
26
- "paymentReceiptRegistry": "0x36f0cd94A286b011b8C6106E69E14567fb7A498e",
27
- "permissionlessSubregistry": "0xE37E1da21Bcce70b515d2f44d84D757c358b96B6",
28
- "permissionlessSubregistryDemoAgent": "0xeE2Db355624BdB4a7551604229EbE72683f8fD85",
29
- "quorumEnforcer": "0xd030196bD6Ba6a654e6E8f7e3609aAd470122422",
30
- "relationshipTypeRegistry": "0x8D5f597f2dE53CC8Ed1a948abF972F8C85301a17",
31
- "shapeRegistry": "0x41273A14e77d7dA256c05276B95D8F2054C54930",
32
- "skillDefinitionRegistry": "0x9bcd76e8E7e5E57863dca0631F44707974cBa58B",
33
- "smartAgentPaymaster": "0xb48Ccecb9118D579204868850f62feb4653c1469",
34
- "timestampEnforcer": "0x5ce38463DcE9c910F09a14e6D0650258e72eEcCA",
35
- "universalSignatureValidator": "0x4BC3Ea8920c87638e0612007eb9de0d70ee4Ba8f",
36
- "valueEnforcer": "0x45170540Ba4d90C7c27103FBF4B136c5EdA545BB"
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,11 +456,37 @@
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",
449
467
  "inputs": []
450
468
  },
469
+ {
470
+ "type": "error",
471
+ "name": "TimelockBelowFloor",
472
+ "inputs": [
473
+ {
474
+ "name": "tier",
475
+ "type": "uint8",
476
+ "internalType": "uint8"
477
+ },
478
+ {
479
+ "name": "provided",
480
+ "type": "uint32",
481
+ "internalType": "uint32"
482
+ },
483
+ {
484
+ "name": "floorSecs",
485
+ "type": "uint32",
486
+ "internalType": "uint32"
487
+ }
488
+ ]
489
+ },
451
490
  {
452
491
  "type": "error",
453
492
  "name": "TooManyInitialCustodians",
@@ -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
@@ -8,7 +8,6 @@ export interface Deployments {
8
8
  readonly "agentNameResolver": Address;
9
9
  readonly "agentNameUniversalResolver": Address;
10
10
  readonly "agentProfileResolver": Address;
11
- readonly "agentRegistryBase": Address;
12
11
  readonly "agentRelationship": Address;
13
12
  readonly "agreementRegistry": Address;
14
13
  readonly "allowedMethodsEnforcer": Address;
@@ -24,7 +23,6 @@ export interface Deployments {
24
23
  readonly "mockUsdc": Address;
25
24
  readonly "ontologyTermRegistry": Address;
26
25
  readonly "paymentEnforcer": Address;
27
- readonly "paymentEscrow": Address;
28
26
  readonly "paymentReceiptRegistry": Address;
29
27
  readonly "permissionlessSubregistry": Address;
30
28
  readonly "permissionlessSubregistryDemoAgent": Address;
@@ -36,7 +34,12 @@ export interface Deployments {
36
34
  readonly "timestampEnforcer": Address;
37
35
  readonly "universalSignatureValidator": Address;
38
36
  readonly "valueEnforcer": Address;
37
+ readonly "agentRegistryBase": 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": "0x1D3BF769B3991faA7847872cE05FA22beE2f07e5",
5
- "agentAccountImplementation": "0xd96eA06208140763256899727B22A1DF7A09387d",
6
- "agentNameRegistry": "0x4e5a6369C91B9093ad17bF0eAc8d344F1b41EdE0",
7
- "agentNameResolver": "0x776a5bADb7DBE238048542E0c91f7a86933C8986",
8
- "agentNameUniversalResolver": "0x8539fad5B148512775cD3712bb55F2fd5f1C85cB",
9
- "agentProfileResolver": "0x82dBC51a77A92A51b177FFE97181cD40aa1c24ab",
10
- "agentRegistryBase": "0x54f76a5faab995f194cc61c50eb5e272c8d85cf4",
11
- "agentRelationship": "0x763c164d8275F76A806721B423aaB5ad6cb4fEA1",
12
- "agreementRegistry": "0xaD300f03EdDf8F015D5583feC8D5F2D1BBC6f854",
13
- "allowedMethodsEnforcer": "0xa149A31F32789cDBfd5f0eed1CF92E7BCb91b549",
14
- "allowedTargetsEnforcer": "0xfb78589C8a9f464BD1e9A340BC809CEe7949b17c",
15
- "approvedHashRegistry": "0x7152282bB71692E7f73ff31DdB43f4a50818845b",
16
- "attestationRegistry": "0x9f9bCAF7b238b87c6d7897767c473b6f8C55C0a6",
17
- "callDataHashEnforcer": "0x0fCE11eC016bd4Bc3a60951FbE4e9Fe7087955b1",
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",
18
17
  "chainId": 84532,
19
- "custodyPolicy": "0xF408e54dA113Fe6b785615750c6Bab6F9008A9d9",
20
- "delegationManager": "0xaCdB7001dB8305c23703f6DB0EfB8B9BC1d75D62",
18
+ "custodyPolicy": "0x5DB542eeBa652372afE6B4b0Cd40D999e65846de",
19
+ "delegationManager": "0x9eD1dC0FD2284fcd4967beeF3317129fee7a92e5",
21
20
  "deployer": "0x31ed17fb99e82E02085Ab4B3cbdaB05489098b44",
22
- "entryPoint": "0x9Eb5F84E8323aACD4AD61b4b980aDB23B15c2903",
23
- "geoFeatureRegistry": "0x74AEb56420a8630c611c36b3053780d90191f94d",
24
- "mockUsdc": "0x07190E7586a468E808D6bd58dC3CEdEC0b25B8E3",
25
- "ontologyTermRegistry": "0x69670d24AcE8C47a294231a1fdC4207642669a25",
26
- "paymentEnforcer": "0xF08946A2c4eed77f366AfDc39AE150F2262E5d29",
27
- "paymentEscrow": "0x30f0fd53dc1245062962b498be3a7e9641cc7c6c",
28
- "paymentReceiptRegistry": "0x36f0cd94A286b011b8C6106E69E14567fb7A498e",
29
- "permissionlessSubregistry": "0xE37E1da21Bcce70b515d2f44d84D757c358b96B6",
30
- "permissionlessSubregistryDemoAgent": "0xeE2Db355624BdB4a7551604229EbE72683f8fD85",
31
- "quorumEnforcer": "0xd030196bD6Ba6a654e6E8f7e3609aAd470122422",
32
- "relationshipTypeRegistry": "0x8D5f597f2dE53CC8Ed1a948abF972F8C85301a17",
33
- "shapeRegistry": "0x41273A14e77d7dA256c05276B95D8F2054C54930",
34
- "skillDefinitionRegistry": "0x9bcd76e8E7e5E57863dca0631F44707974cBa58B",
35
- "smartAgentPaymaster": "0xb48Ccecb9118D579204868850f62feb4653c1469",
36
- "timestampEnforcer": "0x5ce38463DcE9c910F09a14e6D0650258e72eEcCA",
37
- "universalSignatureValidator": "0x4BC3Ea8920c87638e0612007eb9de0d70ee4Ba8f",
38
- "valueEnforcer": "0x45170540Ba4d90C7c27103FBF4B136c5EdA545BB"
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.15",
3
+ "version": "1.0.0-alpha.17",
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
 
@@ -547,25 +547,39 @@ contract AgentAccount is
547
547
  _upgradeAuthorizedCtx = false;
548
548
  }
549
549
 
550
- /// @notice Cancel a queued upgrade during the timelock window. Owner
551
- /// signs a digest that binds to the pending implementation
552
- /// AND `address(this)` + chain id, preventing cross-account
553
- /// replay of a cancel-grant.
550
+ /// @notice Cancel a queued upgrade during the timelock window.
551
+ /// @dev NEW-CANCEL-UPGRADE-1: cancel is a governance op. On a CUSTODY-GOVERNED
552
+ /// account (mode>0 / org) it MUST go through the custody quorum — routed via
553
+ /// the CustodyPolicy executor (`_custodyGovCtx`), exactly like `scheduleUpgrade`
554
+ /// and the other governance mutators — so a single compromised custodian's
555
+ /// ECDSA signature cannot perpetually cancel quorum-scheduled upgrades
556
+ /// (upgrade-liveness DoS). The lightweight ECDSA cancel-grant fast-path remains
557
+ /// ONLY for non-governed (mode-0) accounts, where the sole custodian IS the owner.
554
558
  /// @param ownerSig Owner ECDSA signature over `keccak256(abi.encode(
555
559
  /// "UPGRADE_CANCEL", _pendingUpgrade.newImplementation,
556
- /// address(this), block.chainid))`.
560
+ /// address(this), block.chainid))`. Ignored on governed accounts
561
+ /// (the quorum context authorizes; no signature is consulted).
557
562
  function cancelPendingUpgrade(bytes calldata ownerSig) external {
563
+ bool governed = _hasCustodyGovernance();
564
+ // Governed: authorize FIRST (fail-closed before revealing pending state). Only the custody quorum
565
+ // (executor self-call with the gov context set) may cancel — `_custodyGovCtx` is set solely by
566
+ // `executeFromModule` when the caller is the CustodyPolicy module, so this reverts
567
+ // AdminRequiresCustodyQuorum for any single-custodian / external attempt.
568
+ if (governed) _requireCustodyGoverned();
558
569
  PendingUpgrade memory p = _pendingUpgrade;
559
570
  if (p.readyAt == 0) revert NoPendingUpgrade();
560
- bytes32 digest = keccak256(
561
- abi.encode(
562
- bytes32("UPGRADE_CANCEL"),
563
- p.newImplementation,
564
- address(this),
565
- block.chainid
566
- )
567
- );
568
- if (!_verifyEcdsa(digest, ownerSig)) revert NotOwnerSig();
571
+ if (!governed) {
572
+ // Non-governed (mode-0): the sole custodian's ECDSA cancel-grant authorizes.
573
+ bytes32 digest = keccak256(
574
+ abi.encode(
575
+ bytes32("UPGRADE_CANCEL"),
576
+ p.newImplementation,
577
+ address(this),
578
+ block.chainid
579
+ )
580
+ );
581
+ if (!_verifyEcdsa(digest, ownerSig)) revert NotOwnerSig();
582
+ }
569
583
  delete _pendingUpgrade;
570
584
  emit UpgradeCancelled(p.newImplementation);
571
585
  }
@@ -1501,15 +1515,23 @@ contract AgentAccount is
1501
1515
  }
1502
1516
 
1503
1517
  /// @notice Deterministically derive the Passkey-Identity-Address for
1504
- /// a P-256 public key. Exposed as `pure` so off-chain code +
1505
- /// other contracts (CustodyPolicy, factory) can recompute it
1506
- /// without reading account state.
1507
- 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) {
1508
1530
  return _passkeyIdentity(x, y);
1509
1531
  }
1510
1532
 
1511
- function _passkeyIdentity(uint256 x, uint256 y) internal pure returns (address) {
1512
- 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))))));
1513
1535
  }
1514
1536
 
1515
1537
  /// @inheritdoc IAgentAccount
@@ -1608,7 +1630,14 @@ contract AgentAccount is
1608
1630
  assembly { $.slot := slot }
1609
1631
  }
1610
1632
 
1611
- 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);
1612
1641
  event PasskeyRemoved(bytes32 indexed credentialIdDigest);
1613
1642
 
1614
1643
  /// @notice Register a new WebAuthn credential bound to a specific RP.
@@ -1644,7 +1673,7 @@ contract AgentAccount is
1644
1673
  $.piaToCredentialId[pia] = credentialIdDigest;
1645
1674
  $.rpIdHashOf[credentialIdDigest] = rpIdHash;
1646
1675
  $.count += 1;
1647
- emit PasskeyAdded(credentialIdDigest, x, y, rpIdHash);
1676
+ emit PasskeyAdded(credentialIdDigest);
1648
1677
  emit CustodianAdded(pia);
1649
1678
  }
1650
1679
 
@@ -1679,6 +1708,14 @@ contract AgentAccount is
1679
1708
  return (k.x, k.y);
1680
1709
  }
1681
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
+
1682
1719
  /// @notice Total count of registered passkeys.
1683
1720
  function passkeyCount() external view returns (uint256) {
1684
1721
  return _passkeyStorage().count;
@@ -80,6 +80,10 @@ contract AgentAccountFactory is GovernanceManaged {
80
80
  /// @notice ACCT-M1 (spec 300): a mode-3 (org) account needs ≥2 signers so its separation-of-duties
81
81
  /// (disjoint propose + apply quorums) is satisfiable — a 1-signer org can never split duties.
82
82
  error InfeasibleOrgConfig(uint8 nSigners);
83
+ /// @notice EXT-TL-FLOOR-1 (external audit P1-2): a mode>0 timelock override is below the on-chain product
84
+ /// floor. Overrides may RAISE a safety delay but never LOWER it below the marketed minimum
85
+ /// (spec 300 — the T5/recovery guarantee is a protocol invariant, not a UI convention).
86
+ error TimelockBelowFloor(uint8 tier, uint32 provided, uint32 floorSecs);
83
87
  error ZeroAddress();
84
88
  /// @notice R9.6 / ATL-SEC-05 -- thrown when `params.custodians.length`
85
89
  /// exceeds `MAX_INITIAL_CUSTODIANS`. Without this cap,
@@ -97,6 +101,25 @@ contract AgentAccountFactory is GovernanceManaged {
97
101
  /// threshold at `_buildValidatorInitData:252`.
98
102
  uint256 public constant MAX_INITIAL_CUSTODIANS = 32;
99
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
+
100
123
  constructor(
101
124
  IEntryPoint entryPoint_,
102
125
  address delegationManager_,
@@ -172,7 +195,7 @@ contract AgentAccountFactory is GovernanceManaged {
172
195
  account = AgentAccount(payable(address(proxy)));
173
196
 
174
197
  if (params.mode > 0) {
175
- bytes memory validatorInit = _buildValidatorInitData(params, timelockOverrides);
198
+ bytes memory validatorInit = _buildValidatorInitData(params, timelockOverrides, address(account));
176
199
  account.installModule(2 /* MODULE_TYPE_EXECUTOR */, custodyPolicy, validatorInit);
177
200
  }
178
201
 
@@ -277,6 +300,15 @@ contract AgentAccountFactory is GovernanceManaged {
277
300
  revert TooManyInitialCustodians(params.custodians.length, MAX_INITIAL_CUSTODIANS);
278
301
  }
279
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
+
280
312
  if (params.mode == 0) return;
281
313
 
282
314
  uint256 nTrustees = params.trustees.length;
@@ -301,7 +333,8 @@ contract AgentAccountFactory is GovernanceManaged {
301
333
  /// external custodians + (1 if initial passkey, else 0).
302
334
  function _buildValidatorInitData(
303
335
  AgentAccountInitParams calldata params,
304
- uint32[7] calldata timelockOverrides
336
+ uint32[7] calldata timelockOverrides,
337
+ address account
305
338
  ) internal view returns (bytes memory) {
306
339
  uint256 nSigners = params.custodians.length;
307
340
  if (params.initialPasskeyX != 0 && params.initialPasskeyY != 0) nSigners++;
@@ -329,12 +362,32 @@ contract AgentAccountFactory is GovernanceManaged {
329
362
  timelocks[5] = timelockOverrides[5] == 0 ? uint32(24 hours) : timelockOverrides[5];
330
363
  timelocks[6] = timelockOverrides[6] == 0 ? uint32(48 hours) : timelockOverrides[6];
331
364
 
365
+ // EXT-TL-FLOOR-1 (external audit P1-2): a timelock override may RAISE a safety delay but NEVER lower it
366
+ // below the product floor. A zero override inherits the floor default above; a non-zero override below
367
+ // the floor reverts, so a mode>0 (custody-governed) account can never deploy with sub-floor T4/T5/T6
368
+ // (recovery = T6) delays. The "T5=24h / recovery=48h" guarantee becomes a protocol invariant, not a UI
369
+ // convention (spec 300 — raise-only). Demo/testnet fast-timelock deploys use zero overrides (defaults).
370
+ if (timelocks[4] < 1 hours) revert TimelockBelowFloor(4, timelocks[4], uint32(1 hours));
371
+ if (timelocks[5] < 24 hours) revert TimelockBelowFloor(5, timelocks[5], uint32(24 hours));
372
+ if (timelocks[6] < 48 hours) revert TimelockBelowFloor(6, timelocks[6], uint32(48 hours));
373
+
332
374
  uint8 recThr = uint8(params.trustees.length / 2 + 1);
333
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
+
334
387
  return abi.encode(
335
388
  params.mode,
336
389
  recThr,
337
- params.trustees,
390
+ trustees,
338
391
  thresholds,
339
392
  timelocks,
340
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
  }