opmsec 0.1.0

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 (57) hide show
  1. package/.env.example +14 -0
  2. package/.pnp.cjs +9953 -0
  3. package/.pnp.loader.mjs +2126 -0
  4. package/README.md +266 -0
  5. package/bun.lock +620 -0
  6. package/bunfig.toml +6 -0
  7. package/docker-compose.yml +10 -0
  8. package/package.json +39 -0
  9. package/packages/cli/package.json +7 -0
  10. package/packages/cli/src/commands/audit.tsx +142 -0
  11. package/packages/cli/src/commands/author-view.tsx +247 -0
  12. package/packages/cli/src/commands/info.tsx +109 -0
  13. package/packages/cli/src/commands/install.tsx +362 -0
  14. package/packages/cli/src/commands/passthrough.tsx +36 -0
  15. package/packages/cli/src/commands/push.tsx +321 -0
  16. package/packages/cli/src/components/AgentScores.tsx +32 -0
  17. package/packages/cli/src/components/AuthorInfo.tsx +45 -0
  18. package/packages/cli/src/components/Header.tsx +24 -0
  19. package/packages/cli/src/components/PackageCard.tsx +48 -0
  20. package/packages/cli/src/components/RiskBadge.tsx +32 -0
  21. package/packages/cli/src/components/ScanReport.tsx +50 -0
  22. package/packages/cli/src/components/StatusLine.tsx +30 -0
  23. package/packages/cli/src/index.tsx +111 -0
  24. package/packages/cli/src/services/avatar.ts +10 -0
  25. package/packages/cli/src/services/chainpatrol.ts +25 -0
  26. package/packages/cli/src/services/contract.ts +182 -0
  27. package/packages/cli/src/services/ens.ts +143 -0
  28. package/packages/cli/src/services/fileverse.ts +36 -0
  29. package/packages/cli/src/services/osv.ts +141 -0
  30. package/packages/cli/src/services/signature.ts +22 -0
  31. package/packages/cli/src/services/version.ts +10 -0
  32. package/packages/contracts/contracts/OPMRegistry.sol +253 -0
  33. package/packages/contracts/hardhat.config.ts +32 -0
  34. package/packages/contracts/package-lock.json +7772 -0
  35. package/packages/contracts/package.json +10 -0
  36. package/packages/contracts/scripts/deploy.ts +28 -0
  37. package/packages/contracts/test/OPMRegistry.test.ts +101 -0
  38. package/packages/contracts/tsconfig.json +11 -0
  39. package/packages/core/package.json +7 -0
  40. package/packages/core/src/abi.ts +629 -0
  41. package/packages/core/src/constants.ts +30 -0
  42. package/packages/core/src/index.ts +5 -0
  43. package/packages/core/src/prompt.ts +111 -0
  44. package/packages/core/src/types.ts +104 -0
  45. package/packages/core/src/utils.ts +50 -0
  46. package/packages/scanner/package.json +6 -0
  47. package/packages/scanner/src/agents/agent-configs.ts +24 -0
  48. package/packages/scanner/src/agents/base-agent.ts +75 -0
  49. package/packages/scanner/src/index.ts +25 -0
  50. package/packages/scanner/src/queue/memory-queue.ts +91 -0
  51. package/packages/scanner/src/services/contract-writer.ts +34 -0
  52. package/packages/scanner/src/services/fileverse.ts +89 -0
  53. package/packages/scanner/src/services/npm-registry.ts +159 -0
  54. package/packages/scanner/src/services/openrouter.ts +86 -0
  55. package/packages/scanner/src/services/osv.ts +87 -0
  56. package/packages/scanner/src/services/report-formatter.ts +134 -0
  57. package/tsconfig.json +23 -0
@@ -0,0 +1,253 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ contract OPMRegistry {
5
+ struct AuthorProfile {
6
+ address addr;
7
+ string ensName;
8
+ uint256 reputationTotal;
9
+ uint256 reputationCount;
10
+ uint256 packagesPublished;
11
+ }
12
+
13
+ struct AgentScore {
14
+ address agent;
15
+ uint8 riskScore;
16
+ string reasoning;
17
+ }
18
+
19
+ struct VersionData {
20
+ address author;
21
+ bytes32 checksum;
22
+ bytes signature;
23
+ string reportURI;
24
+ AgentScore[] scores;
25
+ bool exists;
26
+ }
27
+
28
+ struct Package {
29
+ string name;
30
+ string[] versions;
31
+ bool exists;
32
+ }
33
+
34
+ address public owner;
35
+ mapping(address => bool) public authorizedAgents;
36
+ mapping(address => AuthorProfile) public authors;
37
+ mapping(bytes32 => address) public ensToAuthor;
38
+ mapping(bytes32 => Package) internal packages;
39
+ mapping(bytes32 => mapping(bytes32 => VersionData)) internal versionData;
40
+ mapping(address => bytes32[]) internal authorPackages;
41
+
42
+ uint8 public constant HIGH_RISK_THRESHOLD = 70;
43
+ uint8 public constant MEDIUM_RISK_THRESHOLD = 40;
44
+
45
+ event PackageRegistered(string name, string version, address author, string ensName);
46
+ event ScoreSubmitted(string name, string version, address agent, uint8 riskScore, string reasoning);
47
+ event ReportURISet(string name, string version, string uri);
48
+ event AuthorRegistered(address addr, string ensName);
49
+ event AgentAuthorized(address agent, bool status);
50
+
51
+ modifier onlyOwner() {
52
+ require(msg.sender == owner, "Not owner");
53
+ _;
54
+ }
55
+
56
+ modifier onlyAgent() {
57
+ require(authorizedAgents[msg.sender], "Not authorized agent");
58
+ _;
59
+ }
60
+
61
+ constructor() {
62
+ owner = msg.sender;
63
+ }
64
+
65
+ function setAgent(address agent, bool status) external onlyOwner {
66
+ authorizedAgents[agent] = status;
67
+ emit AgentAuthorized(agent, status);
68
+ }
69
+
70
+ function registerPackage(
71
+ string calldata name,
72
+ string calldata version,
73
+ bytes32 checksum,
74
+ bytes calldata sig,
75
+ string calldata ensName
76
+ ) external {
77
+ bytes32 nameHash = keccak256(bytes(name));
78
+ bytes32 versionHash = keccak256(bytes(version));
79
+
80
+ require(!versionData[nameHash][versionHash].exists, "Version already registered");
81
+
82
+ if (!packages[nameHash].exists) {
83
+ packages[nameHash].name = name;
84
+ packages[nameHash].exists = true;
85
+ }
86
+ packages[nameHash].versions.push(version);
87
+
88
+ VersionData storage vd = versionData[nameHash][versionHash];
89
+ vd.author = msg.sender;
90
+ vd.checksum = checksum;
91
+ vd.signature = sig;
92
+ vd.exists = true;
93
+
94
+ if (authors[msg.sender].addr == address(0)) {
95
+ authors[msg.sender].addr = msg.sender;
96
+ authors[msg.sender].ensName = ensName;
97
+ if (bytes(ensName).length > 0) {
98
+ ensToAuthor[keccak256(bytes(ensName))] = msg.sender;
99
+ }
100
+ emit AuthorRegistered(msg.sender, ensName);
101
+ }
102
+ authors[msg.sender].packagesPublished++;
103
+ authorPackages[msg.sender].push(nameHash);
104
+
105
+ emit PackageRegistered(name, version, msg.sender, ensName);
106
+ }
107
+
108
+ function submitScore(
109
+ string calldata name,
110
+ string calldata version,
111
+ uint8 riskScore,
112
+ string calldata reasoning
113
+ ) external onlyAgent {
114
+ bytes32 nameHash = keccak256(bytes(name));
115
+ bytes32 versionHash = keccak256(bytes(version));
116
+ require(versionData[nameHash][versionHash].exists, "Version not found");
117
+
118
+ AgentScore[] storage scores = versionData[nameHash][versionHash].scores;
119
+ for (uint256 i = 0; i < scores.length; i++) {
120
+ require(scores[i].agent != msg.sender, "Agent already scored");
121
+ }
122
+
123
+ scores.push(AgentScore({
124
+ agent: msg.sender,
125
+ riskScore: riskScore,
126
+ reasoning: reasoning
127
+ }));
128
+
129
+ authors[versionData[nameHash][versionHash].author].reputationTotal += riskScore;
130
+ authors[versionData[nameHash][versionHash].author].reputationCount++;
131
+
132
+ emit ScoreSubmitted(name, version, msg.sender, riskScore, reasoning);
133
+ }
134
+
135
+ function setReportURI(
136
+ string calldata name,
137
+ string calldata version,
138
+ string calldata uri
139
+ ) external onlyAgent {
140
+ bytes32 nameHash = keccak256(bytes(name));
141
+ bytes32 versionHash = keccak256(bytes(version));
142
+ require(versionData[nameHash][versionHash].exists, "Version not found");
143
+ versionData[nameHash][versionHash].reportURI = uri;
144
+ emit ReportURISet(name, version, uri);
145
+ }
146
+
147
+ function getAggregateScore(string calldata name, string calldata version) external view returns (uint8) {
148
+ bytes32 nameHash = keccak256(bytes(name));
149
+ bytes32 versionHash = keccak256(bytes(version));
150
+ AgentScore[] storage scores = versionData[nameHash][versionHash].scores;
151
+ if (scores.length == 0) return 0;
152
+
153
+ uint256 total = 0;
154
+ for (uint256 i = 0; i < scores.length; i++) {
155
+ total += scores[i].riskScore;
156
+ }
157
+ return uint8(total / scores.length);
158
+ }
159
+
160
+ function getSafestVersion(string calldata name, uint8 lookback) external view returns (string memory) {
161
+ bytes32 nameHash = keccak256(bytes(name));
162
+ require(packages[nameHash].exists, "Package not found");
163
+
164
+ string[] storage vers = packages[nameHash].versions;
165
+ uint256 start = vers.length > lookback ? vers.length - lookback : 0;
166
+ uint256 bestScore = type(uint256).max;
167
+ string memory bestVersion = "";
168
+
169
+ for (uint256 i = start; i < vers.length; i++) {
170
+ bytes32 vh = keccak256(bytes(vers[i]));
171
+ AgentScore[] storage scores = versionData[nameHash][vh].scores;
172
+ if (scores.length == 0) continue;
173
+
174
+ uint256 total = 0;
175
+ for (uint256 j = 0; j < scores.length; j++) {
176
+ total += scores[j].riskScore;
177
+ }
178
+ uint256 avg = total / scores.length;
179
+ if (avg < bestScore) {
180
+ bestScore = avg;
181
+ bestVersion = vers[i];
182
+ }
183
+ }
184
+ return bestVersion;
185
+ }
186
+
187
+ function getPackageInfo(
188
+ string calldata name,
189
+ string calldata version
190
+ ) external view returns (
191
+ address author,
192
+ bytes32 checksum,
193
+ bytes memory sig,
194
+ string memory ensName,
195
+ string memory reportURI,
196
+ uint8 aggregateScore,
197
+ bool exists
198
+ ) {
199
+ bytes32 nameHash = keccak256(bytes(name));
200
+ bytes32 versionHash = keccak256(bytes(version));
201
+ VersionData storage vd = versionData[nameHash][versionHash];
202
+
203
+ if (!vd.exists) {
204
+ return (address(0), bytes32(0), "", "", "", 0, false);
205
+ }
206
+
207
+ uint256 total = 0;
208
+ for (uint256 i = 0; i < vd.scores.length; i++) {
209
+ total += vd.scores[i].riskScore;
210
+ }
211
+ uint8 avgScore = vd.scores.length > 0 ? uint8(total / vd.scores.length) : 0;
212
+
213
+ return (
214
+ vd.author,
215
+ vd.checksum,
216
+ vd.signature,
217
+ authors[vd.author].ensName,
218
+ vd.reportURI,
219
+ avgScore,
220
+ true
221
+ );
222
+ }
223
+
224
+ function getScores(
225
+ string calldata name,
226
+ string calldata version
227
+ ) external view returns (AgentScore[] memory) {
228
+ bytes32 nameHash = keccak256(bytes(name));
229
+ bytes32 versionHash = keccak256(bytes(version));
230
+ return versionData[nameHash][versionHash].scores;
231
+ }
232
+
233
+ function getVersions(string calldata name) external view returns (string[] memory) {
234
+ bytes32 nameHash = keccak256(bytes(name));
235
+ return packages[nameHash].versions;
236
+ }
237
+
238
+ function getAuthorByAddress(address addr) external view returns (AuthorProfile memory) {
239
+ return authors[addr];
240
+ }
241
+
242
+ function getAuthorByENS(string calldata ensName) external view returns (AuthorProfile memory) {
243
+ address addr = ensToAuthor[keccak256(bytes(ensName))];
244
+ require(addr != address(0), "ENS not found");
245
+ return authors[addr];
246
+ }
247
+
248
+ function getAuthorReputation(address addr) external view returns (uint256) {
249
+ AuthorProfile storage a = authors[addr];
250
+ if (a.reputationCount == 0) return 0;
251
+ return a.reputationTotal / a.reputationCount;
252
+ }
253
+ }
@@ -0,0 +1,32 @@
1
+ import { HardhatUserConfig } from "hardhat/config";
2
+ import "@nomicfoundation/hardhat-toolbox";
3
+ import * as dotenv from "dotenv";
4
+ dotenv.config({ path: "../../.env" });
5
+
6
+ const config: HardhatUserConfig = {
7
+ solidity: "0.8.20",
8
+ networks: {
9
+ baseSepolia: {
10
+ url: process.env.BASE_SEPOLIA_RPC_URL || "https://sepolia.base.org",
11
+ accounts: process.env.OPM_PRIVATE_KEY ? [process.env.OPM_PRIVATE_KEY] : [],
12
+ chainId: 84532,
13
+ },
14
+ },
15
+ etherscan: {
16
+ apiKey: {
17
+ baseSepolia: process.env.BASESCAN_API_KEY || "",
18
+ },
19
+ customChains: [
20
+ {
21
+ network: "baseSepolia",
22
+ chainId: 84532,
23
+ urls: {
24
+ apiURL: "https://api-sepolia.basescan.org/api",
25
+ browserURL: "https://sepolia.basescan.org",
26
+ },
27
+ },
28
+ ],
29
+ },
30
+ };
31
+
32
+ export default config;