opmsec 0.1.0 → 0.1.3

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.
Files changed (124) hide show
  1. package/.env.example +23 -13
  2. package/README.md +256 -173
  3. package/docs/architecture/agents.mdx +77 -0
  4. package/docs/architecture/benchmarks.mdx +65 -0
  5. package/docs/architecture/overview.mdx +58 -0
  6. package/docs/architecture/scanner.mdx +53 -0
  7. package/docs/cli/audit.mdx +35 -0
  8. package/docs/cli/check.mdx +44 -0
  9. package/docs/cli/fix.mdx +49 -0
  10. package/docs/cli/info.mdx +44 -0
  11. package/docs/cli/install.mdx +71 -0
  12. package/docs/cli/push.mdx +99 -0
  13. package/docs/cli/register-agent.mdx +80 -0
  14. package/docs/cli/view.mdx +52 -0
  15. package/docs/concepts/multi-agent-consensus.mdx +58 -0
  16. package/docs/concepts/on-chain-registry.mdx +74 -0
  17. package/docs/concepts/security-model.mdx +76 -0
  18. package/docs/concepts/zk-agent-verification.mdx +82 -0
  19. package/docs/configuration.mdx +82 -0
  20. package/docs/contract/deployment.mdx +57 -0
  21. package/docs/contract/events.mdx +115 -0
  22. package/docs/contract/functions.mdx +220 -0
  23. package/docs/contract/overview.mdx +58 -0
  24. package/docs/favicon.svg +5 -0
  25. package/docs/introduction.mdx +43 -0
  26. package/docs/logo/dark.svg +5 -0
  27. package/docs/logo/light.svg +5 -0
  28. package/docs/mint.json +106 -0
  29. package/docs/quickstart.mdx +133 -0
  30. package/package.json +3 -3
  31. package/packages/cli/src/commands/author-view.tsx +9 -1
  32. package/packages/cli/src/commands/check.tsx +318 -0
  33. package/packages/cli/src/commands/fix.tsx +294 -0
  34. package/packages/cli/src/commands/install.tsx +229 -33
  35. package/packages/cli/src/commands/push.tsx +53 -22
  36. package/packages/cli/src/commands/register-agent.tsx +227 -0
  37. package/packages/cli/src/components/AgentScores.tsx +20 -6
  38. package/packages/cli/src/components/Hyperlink.tsx +30 -0
  39. package/packages/cli/src/components/ScanReport.tsx +3 -2
  40. package/packages/cli/src/index.tsx +41 -5
  41. package/packages/cli/src/services/avatar.ts +43 -6
  42. package/packages/cli/src/services/chainpatrol.ts +20 -17
  43. package/packages/cli/src/services/contract.ts +41 -8
  44. package/packages/cli/src/services/ens.ts +3 -5
  45. package/packages/cli/src/services/fileverse.ts +12 -13
  46. package/packages/cli/src/services/typosquat.ts +166 -0
  47. package/packages/contracts/circuits/accuracy_verifier.circom +101 -0
  48. package/packages/contracts/contracts/OPMRegistry.sol +63 -0
  49. package/packages/contracts/scripts/deploy.ts +22 -3
  50. package/packages/core/src/abi.ts +221 -0
  51. package/packages/core/src/benchmarks.ts +450 -0
  52. package/packages/core/src/constants.ts +20 -0
  53. package/packages/core/src/index.ts +2 -0
  54. package/packages/core/src/model-rankings.ts +115 -0
  55. package/packages/core/src/prompt.ts +58 -0
  56. package/packages/core/src/types.ts +41 -0
  57. package/packages/core/src/utils.ts +7 -3
  58. package/packages/scanner/src/agents/base-agent.ts +13 -3
  59. package/packages/scanner/src/index.ts +5 -2
  60. package/packages/scanner/src/queue/memory-queue.ts +8 -3
  61. package/packages/scanner/src/services/benchmark-runner.ts +114 -0
  62. package/packages/scanner/src/services/contract-writer.ts +2 -3
  63. package/packages/scanner/src/services/fileverse.ts +26 -7
  64. package/packages/scanner/src/services/openrouter.ts +46 -0
  65. package/packages/scanner/src/services/report-formatter.ts +122 -3
  66. package/packages/scanner/src/services/zk-verifier.ts +118 -0
  67. package/packages/web/.next/app-build-manifest.json +15 -0
  68. package/packages/web/.next/build-manifest.json +20 -0
  69. package/packages/web/.next/package.json +1 -0
  70. package/packages/web/.next/prerender-manifest.json +11 -0
  71. package/packages/web/.next/react-loadable-manifest.json +1 -0
  72. package/packages/web/.next/routes-manifest.json +1 -0
  73. package/packages/web/.next/server/app/page.js +272 -0
  74. package/packages/web/.next/server/app/page_client-reference-manifest.js +1 -0
  75. package/packages/web/.next/server/app-paths-manifest.json +3 -0
  76. package/packages/web/.next/server/interception-route-rewrite-manifest.js +1 -0
  77. package/packages/web/.next/server/middleware-build-manifest.js +22 -0
  78. package/packages/web/.next/server/middleware-manifest.json +6 -0
  79. package/packages/web/.next/server/middleware-react-loadable-manifest.js +1 -0
  80. package/packages/web/.next/server/next-font-manifest.js +1 -0
  81. package/packages/web/.next/server/next-font-manifest.json +1 -0
  82. package/packages/web/.next/server/pages-manifest.json +1 -0
  83. package/packages/web/.next/server/server-reference-manifest.js +1 -0
  84. package/packages/web/.next/server/server-reference-manifest.json +5 -0
  85. package/packages/web/.next/server/vendor-chunks/@swc.js +55 -0
  86. package/packages/web/.next/server/vendor-chunks/next.js +3010 -0
  87. package/packages/web/.next/server/webpack-runtime.js +209 -0
  88. package/packages/web/.next/static/chunks/app/layout.js +39 -0
  89. package/packages/web/.next/static/chunks/app/page.js +61 -0
  90. package/packages/web/.next/static/chunks/app-pages-internals.js +182 -0
  91. package/packages/web/.next/static/chunks/main-app.js +1882 -0
  92. package/packages/web/.next/static/chunks/polyfills.js +1 -0
  93. package/packages/web/.next/static/chunks/webpack.js +1393 -0
  94. package/packages/web/.next/static/css/app/layout.css +1237 -0
  95. package/packages/web/.next/static/development/_buildManifest.js +1 -0
  96. package/packages/web/.next/static/development/_ssgManifest.js +1 -0
  97. package/packages/web/.next/static/webpack/633457081244afec._.hot-update.json +1 -0
  98. package/packages/web/.next/static/webpack/6fee6306e0f98869.webpack.hot-update.json +1 -0
  99. package/packages/web/.next/static/webpack/73e341375c8d429e.webpack.hot-update.json +1 -0
  100. package/packages/web/.next/static/webpack/app/layout.6fee6306e0f98869.hot-update.js +22 -0
  101. package/packages/web/.next/static/webpack/app/layout.73e341375c8d429e.hot-update.js +22 -0
  102. package/packages/web/.next/static/webpack/app/page.6fee6306e0f98869.hot-update.js +22 -0
  103. package/packages/web/.next/static/webpack/app/page.73e341375c8d429e.hot-update.js +22 -0
  104. package/packages/web/.next/static/webpack/webpack.6fee6306e0f98869.hot-update.js +12 -0
  105. package/packages/web/.next/static/webpack/webpack.73e341375c8d429e.hot-update.js +12 -0
  106. package/packages/web/.next/trace +5 -0
  107. package/packages/web/.next/types/app/layout.ts +84 -0
  108. package/packages/web/.next/types/app/page.ts +84 -0
  109. package/packages/web/.next/types/cache-life.d.ts +141 -0
  110. package/packages/web/.next/types/package.json +1 -0
  111. package/packages/web/.next/types/routes.d.ts +57 -0
  112. package/packages/web/.next/types/validator.ts +61 -0
  113. package/packages/web/app/globals.css +75 -0
  114. package/packages/web/app/layout.tsx +26 -0
  115. package/packages/web/app/page.tsx +358 -0
  116. package/packages/web/bun.lock +300 -0
  117. package/packages/web/next-env.d.ts +6 -0
  118. package/packages/web/next.config.ts +5 -0
  119. package/packages/web/package.json +26 -0
  120. package/packages/web/postcss.config.mjs +8 -0
  121. package/packages/web/public/favicon.svg +5 -0
  122. package/packages/web/public/logo.svg +7 -0
  123. package/packages/web/tailwind.config.ts +48 -0
  124. package/packages/web/tsconfig.json +21 -0
@@ -0,0 +1,101 @@
1
+ pragma circom 2.1.0;
2
+
3
+ include "node_modules/circomlib/circuits/comparators.circom";
4
+ include "node_modules/circomlib/circuits/poseidon.circom";
5
+
6
+ /**
7
+ * AccuracyVerifier circuit for OPM agent registration.
8
+ *
9
+ * Proves that a candidate agent achieved 100% accuracy on a
10
+ * benchmark suite without revealing the individual test results
11
+ * or the expected outputs.
12
+ *
13
+ * Private inputs:
14
+ * - expected[N]: expected risk level ordinals (0=LOW, 1=MEDIUM, 2=HIGH, 3=CRITICAL)
15
+ * - actual[N]: actual risk level ordinals from the candidate agent
16
+ * - salt: random blinding factor for the commitment
17
+ *
18
+ * Public inputs:
19
+ * - commitmentHash: Poseidon hash of (salt, expected[0..N-1])
20
+ *
21
+ * Public outputs:
22
+ * - passed: 1 if all expected[i] == actual[i], 0 otherwise
23
+ * - proofHash: Poseidon hash binding the result to the commitment
24
+ *
25
+ * Compilation:
26
+ * circom accuracy_verifier.circom --r1cs --wasm --sym -o build/
27
+ *
28
+ * Trusted setup:
29
+ * snarkjs groth16 setup build/accuracy_verifier.r1cs pot12_final.ptau build/accuracy_verifier_0000.zkey
30
+ * snarkjs zkey contribute build/accuracy_verifier_0000.zkey build/accuracy_verifier_final.zkey --name="opm-ceremony"
31
+ * snarkjs zkey export verificationkey build/accuracy_verifier_final.zkey build/verification_key.json
32
+ *
33
+ * Prove:
34
+ * snarkjs groth16 prove build/accuracy_verifier_final.zkey build/accuracy_verifier_js/accuracy_verifier.wasm input.json build/proof.json build/public.json
35
+ *
36
+ * Verify:
37
+ * snarkjs groth16 verify build/verification_key.json build/public.json build/proof.json
38
+ *
39
+ * Export Solidity verifier:
40
+ * snarkjs zkey export solidityverifier build/accuracy_verifier_final.zkey contracts/AccuracyVerifier.sol
41
+ */
42
+
43
+ template AccuracyVerifier(N) {
44
+ // Private inputs
45
+ signal input expected[N];
46
+ signal input actual[N];
47
+ signal input salt;
48
+
49
+ // Public inputs
50
+ signal input commitmentHash;
51
+
52
+ // Public outputs
53
+ signal output passed;
54
+ signal output proofHash;
55
+
56
+ // Step 1: Verify commitment — hash(salt, expected[0..N-1]) must equal commitmentHash
57
+ // We chain Poseidon hashes since Poseidon has a limited arity
58
+ component commitHashers[N];
59
+ signal commitChain[N + 1];
60
+ commitChain[0] <== salt;
61
+
62
+ for (var i = 0; i < N; i++) {
63
+ commitHashers[i] = Poseidon(2);
64
+ commitHashers[i].inputs[0] <== commitChain[i];
65
+ commitHashers[i].inputs[1] <== expected[i];
66
+ commitChain[i + 1] <== commitHashers[i].out;
67
+ }
68
+
69
+ // Verify the commitment matches
70
+ commitChain[N] === commitmentHash;
71
+
72
+ // Step 2: Check equality for each test case
73
+ component isEq[N];
74
+ signal matchBits[N];
75
+
76
+ for (var i = 0; i < N; i++) {
77
+ isEq[i] = IsEqual();
78
+ isEq[i].in[0] <== expected[i];
79
+ isEq[i].in[1] <== actual[i];
80
+ matchBits[i] <== isEq[i].out; // 1 if match, 0 if mismatch
81
+ }
82
+
83
+ // Step 3: Compute product of all match bits (1 iff all match)
84
+ signal product[N];
85
+ product[0] <== matchBits[0];
86
+ for (var i = 1; i < N; i++) {
87
+ product[i] <== product[i - 1] * matchBits[i];
88
+ }
89
+
90
+ passed <== product[N - 1];
91
+
92
+ // Step 4: Compute proof hash binding result to commitment
93
+ component proofHasher = Poseidon(3);
94
+ proofHasher.inputs[0] <== commitmentHash;
95
+ proofHasher.inputs[1] <== passed;
96
+ proofHasher.inputs[2] <== salt;
97
+ proofHash <== proofHasher.out;
98
+ }
99
+
100
+ // Instantiate with 10 benchmark test cases
101
+ component main { public [commitmentHash] } = AccuracyVerifier(10);
@@ -47,6 +47,27 @@ contract OPMRegistry {
47
47
  event ReportURISet(string name, string version, string uri);
48
48
  event AuthorRegistered(address addr, string ensName);
49
49
  event AgentAuthorized(address agent, bool status);
50
+ event AgentRegistered(
51
+ address indexed agent,
52
+ string name,
53
+ string model,
54
+ bytes32 systemPromptHash,
55
+ bytes32 proofHash,
56
+ uint256 timestamp
57
+ );
58
+
59
+ struct RegisteredAgent {
60
+ address agentAddress;
61
+ string name;
62
+ string model;
63
+ bytes32 systemPromptHash;
64
+ bytes32 proofHash;
65
+ uint256 registeredAt;
66
+ bool active;
67
+ }
68
+
69
+ mapping(address => RegisteredAgent) public registeredAgents;
70
+ address[] public agentRegistry;
50
71
 
51
72
  modifier onlyOwner() {
52
73
  require(msg.sender == owner, "Not owner");
@@ -250,4 +271,46 @@ contract OPMRegistry {
250
271
  if (a.reputationCount == 0) return 0;
251
272
  return a.reputationTotal / a.reputationCount;
252
273
  }
274
+
275
+ function registerAgent(
276
+ string calldata name,
277
+ string calldata model,
278
+ bytes32 systemPromptHash,
279
+ bytes32 proofHash
280
+ ) external {
281
+ require(!authorizedAgents[msg.sender], "Agent already authorized");
282
+ require(registeredAgents[msg.sender].agentAddress == address(0), "Agent already registered");
283
+ require(proofHash != bytes32(0), "Invalid proof");
284
+
285
+ registeredAgents[msg.sender] = RegisteredAgent({
286
+ agentAddress: msg.sender,
287
+ name: name,
288
+ model: model,
289
+ systemPromptHash: systemPromptHash,
290
+ proofHash: proofHash,
291
+ registeredAt: block.timestamp,
292
+ active: true
293
+ });
294
+
295
+ agentRegistry.push(msg.sender);
296
+ authorizedAgents[msg.sender] = true;
297
+
298
+ emit AgentRegistered(msg.sender, name, model, systemPromptHash, proofHash, block.timestamp);
299
+ emit AgentAuthorized(msg.sender, true);
300
+ }
301
+
302
+ function getRegisteredAgent(address agent) external view returns (RegisteredAgent memory) {
303
+ return registeredAgents[agent];
304
+ }
305
+
306
+ function getAgentCount() external view returns (uint256) {
307
+ return agentRegistry.length;
308
+ }
309
+
310
+ function revokeAgent(address agent) external onlyOwner {
311
+ require(registeredAgents[agent].active, "Agent not active");
312
+ registeredAgents[agent].active = false;
313
+ authorizedAgents[agent] = false;
314
+ emit AgentAuthorized(agent, false);
315
+ }
253
316
  }
@@ -6,6 +6,11 @@ async function main() {
6
6
 
7
7
  const OPMRegistry = await ethers.getContractFactory("OPMRegistry");
8
8
  const registry = await OPMRegistry.deploy();
9
+ const deployTx = registry.deploymentTransaction();
10
+ if (deployTx) {
11
+ console.log("Deploy tx:", deployTx.hash);
12
+ await deployTx.wait(2);
13
+ }
9
14
  await registry.waitForDeployment();
10
15
 
11
16
  const address = await registry.getAddress();
@@ -14,9 +19,23 @@ async function main() {
14
19
  const agentKey = process.env.AGENT_PRIVATE_KEY;
15
20
  if (agentKey) {
16
21
  const agentWallet = new ethers.Wallet(agentKey);
17
- const tx = await registry.setAgent(agentWallet.address, true);
18
- await tx.wait();
19
- console.log("Authorized agent:", agentWallet.address);
22
+ console.log("Authorizing agent:", agentWallet.address);
23
+
24
+ for (let attempt = 0; attempt < 3; attempt++) {
25
+ try {
26
+ const tx = await registry.setAgent(agentWallet.address, true);
27
+ await tx.wait(2);
28
+ console.log("Authorized agent:", agentWallet.address);
29
+ break;
30
+ } catch (err: any) {
31
+ if (attempt < 2 && err?.message?.includes("nonce")) {
32
+ console.log(`Nonce conflict, retrying (${attempt + 1}/3)...`);
33
+ await new Promise((r) => setTimeout(r, 3000));
34
+ } else {
35
+ throw err;
36
+ }
37
+ }
38
+ }
20
39
  }
21
40
 
22
41
  console.log("\nAdd to .env:\nCONTRACT_ADDRESS=" + address);
@@ -625,5 +625,226 @@ export const OPM_REGISTRY_ABI = [
625
625
  "outputs": [],
626
626
  "stateMutability": "nonpayable",
627
627
  "type": "function"
628
+ },
629
+ {
630
+ "anonymous": false,
631
+ "inputs": [
632
+ {
633
+ "indexed": true,
634
+ "internalType": "address",
635
+ "name": "agent",
636
+ "type": "address"
637
+ },
638
+ {
639
+ "indexed": false,
640
+ "internalType": "string",
641
+ "name": "name",
642
+ "type": "string"
643
+ },
644
+ {
645
+ "indexed": false,
646
+ "internalType": "string",
647
+ "name": "model",
648
+ "type": "string"
649
+ },
650
+ {
651
+ "indexed": false,
652
+ "internalType": "bytes32",
653
+ "name": "systemPromptHash",
654
+ "type": "bytes32"
655
+ },
656
+ {
657
+ "indexed": false,
658
+ "internalType": "bytes32",
659
+ "name": "proofHash",
660
+ "type": "bytes32"
661
+ },
662
+ {
663
+ "indexed": false,
664
+ "internalType": "uint256",
665
+ "name": "timestamp",
666
+ "type": "uint256"
667
+ }
668
+ ],
669
+ "name": "AgentRegistered",
670
+ "type": "event"
671
+ },
672
+ {
673
+ "inputs": [
674
+ {
675
+ "internalType": "string",
676
+ "name": "name",
677
+ "type": "string"
678
+ },
679
+ {
680
+ "internalType": "string",
681
+ "name": "model",
682
+ "type": "string"
683
+ },
684
+ {
685
+ "internalType": "bytes32",
686
+ "name": "systemPromptHash",
687
+ "type": "bytes32"
688
+ },
689
+ {
690
+ "internalType": "bytes32",
691
+ "name": "proofHash",
692
+ "type": "bytes32"
693
+ }
694
+ ],
695
+ "name": "registerAgent",
696
+ "outputs": [],
697
+ "stateMutability": "nonpayable",
698
+ "type": "function"
699
+ },
700
+ {
701
+ "inputs": [
702
+ {
703
+ "internalType": "address",
704
+ "name": "agent",
705
+ "type": "address"
706
+ }
707
+ ],
708
+ "name": "getRegisteredAgent",
709
+ "outputs": [
710
+ {
711
+ "components": [
712
+ {
713
+ "internalType": "address",
714
+ "name": "agentAddress",
715
+ "type": "address"
716
+ },
717
+ {
718
+ "internalType": "string",
719
+ "name": "name",
720
+ "type": "string"
721
+ },
722
+ {
723
+ "internalType": "string",
724
+ "name": "model",
725
+ "type": "string"
726
+ },
727
+ {
728
+ "internalType": "bytes32",
729
+ "name": "systemPromptHash",
730
+ "type": "bytes32"
731
+ },
732
+ {
733
+ "internalType": "bytes32",
734
+ "name": "proofHash",
735
+ "type": "bytes32"
736
+ },
737
+ {
738
+ "internalType": "uint256",
739
+ "name": "registeredAt",
740
+ "type": "uint256"
741
+ },
742
+ {
743
+ "internalType": "bool",
744
+ "name": "active",
745
+ "type": "bool"
746
+ }
747
+ ],
748
+ "internalType": "struct OPMRegistry.RegisteredAgent",
749
+ "name": "",
750
+ "type": "tuple"
751
+ }
752
+ ],
753
+ "stateMutability": "view",
754
+ "type": "function"
755
+ },
756
+ {
757
+ "inputs": [],
758
+ "name": "getAgentCount",
759
+ "outputs": [
760
+ {
761
+ "internalType": "uint256",
762
+ "name": "",
763
+ "type": "uint256"
764
+ }
765
+ ],
766
+ "stateMutability": "view",
767
+ "type": "function"
768
+ },
769
+ {
770
+ "inputs": [
771
+ {
772
+ "internalType": "address",
773
+ "name": "agent",
774
+ "type": "address"
775
+ }
776
+ ],
777
+ "name": "revokeAgent",
778
+ "outputs": [],
779
+ "stateMutability": "nonpayable",
780
+ "type": "function"
781
+ },
782
+ {
783
+ "inputs": [
784
+ {
785
+ "internalType": "address",
786
+ "name": "",
787
+ "type": "address"
788
+ }
789
+ ],
790
+ "name": "registeredAgents",
791
+ "outputs": [
792
+ {
793
+ "internalType": "address",
794
+ "name": "agentAddress",
795
+ "type": "address"
796
+ },
797
+ {
798
+ "internalType": "string",
799
+ "name": "name",
800
+ "type": "string"
801
+ },
802
+ {
803
+ "internalType": "string",
804
+ "name": "model",
805
+ "type": "string"
806
+ },
807
+ {
808
+ "internalType": "bytes32",
809
+ "name": "systemPromptHash",
810
+ "type": "bytes32"
811
+ },
812
+ {
813
+ "internalType": "bytes32",
814
+ "name": "proofHash",
815
+ "type": "bytes32"
816
+ },
817
+ {
818
+ "internalType": "uint256",
819
+ "name": "registeredAt",
820
+ "type": "uint256"
821
+ },
822
+ {
823
+ "internalType": "bool",
824
+ "name": "active",
825
+ "type": "bool"
826
+ }
827
+ ],
828
+ "stateMutability": "view",
829
+ "type": "function"
830
+ },
831
+ {
832
+ "inputs": [
833
+ {
834
+ "internalType": "uint256",
835
+ "name": "",
836
+ "type": "uint256"
837
+ }
838
+ ],
839
+ "name": "agentRegistry",
840
+ "outputs": [
841
+ {
842
+ "internalType": "address",
843
+ "name": "",
844
+ "type": "address"
845
+ }
846
+ ],
847
+ "stateMutability": "view",
848
+ "type": "function"
628
849
  }
629
850
  ] as const;