opmsec 0.1.3 → 0.1.4

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 (90) hide show
  1. package/.husky/pre-commit +1 -0
  2. package/bun.lock +4 -4
  3. package/docs/mint.json +2 -2
  4. package/package.json +7 -6
  5. package/packages/cli/src/commands/install.tsx +282 -24
  6. package/packages/cli/src/index.tsx +3 -1
  7. package/packages/cli/src/services/version.ts +156 -5
  8. package/packages/core/src/utils.ts +135 -0
  9. package/packages/scanner/src/services/openrouter.ts +18 -7
  10. package/packages/web/.next/BUILD_ID +1 -0
  11. package/packages/web/.next/app-build-manifest.json +18 -7
  12. package/packages/web/.next/app-path-routes-manifest.json +4 -0
  13. package/packages/web/.next/build-manifest.json +19 -6
  14. package/packages/web/.next/diagnostics/build-diagnostics.json +6 -0
  15. package/packages/web/.next/diagnostics/framework.json +1 -0
  16. package/packages/web/.next/export-marker.json +6 -0
  17. package/packages/web/.next/images-manifest.json +58 -0
  18. package/packages/web/.next/next-minimal-server.js.nft.json +1 -0
  19. package/packages/web/.next/next-server.js.nft.json +1 -0
  20. package/packages/web/.next/prerender-manifest.json +54 -4
  21. package/packages/web/.next/required-server-files.json +320 -0
  22. package/packages/web/.next/routes-manifest.json +53 -1
  23. package/packages/web/.next/server/app/_not-found/page.js +2 -0
  24. package/packages/web/.next/server/app/_not-found/page.js.nft.json +1 -0
  25. package/packages/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -0
  26. package/packages/web/.next/server/app/_not-found.html +1 -0
  27. package/packages/web/.next/server/app/_not-found.meta +8 -0
  28. package/packages/web/.next/server/app/_not-found.rsc +16 -0
  29. package/packages/web/.next/server/app/index.html +1 -0
  30. package/packages/web/.next/server/app/index.meta +7 -0
  31. package/packages/web/.next/server/app/index.rsc +20 -0
  32. package/packages/web/.next/server/app/page.js +2 -272
  33. package/packages/web/.next/server/app/page.js.nft.json +1 -0
  34. package/packages/web/.next/server/app/page_client-reference-manifest.js +1 -1
  35. package/packages/web/.next/server/app-paths-manifest.json +1 -0
  36. package/packages/web/.next/server/chunks/611.js +6 -0
  37. package/packages/web/.next/server/chunks/778.js +30 -0
  38. package/packages/web/.next/server/functions-config-manifest.json +4 -0
  39. package/packages/web/.next/server/interception-route-rewrite-manifest.js +1 -1
  40. package/packages/web/.next/server/middleware-build-manifest.js +1 -22
  41. package/packages/web/.next/server/middleware-react-loadable-manifest.js +1 -1
  42. package/packages/web/.next/server/next-font-manifest.js +1 -1
  43. package/packages/web/.next/server/pages/404.html +1 -0
  44. package/packages/web/.next/server/pages/500.html +1 -0
  45. package/packages/web/.next/server/pages/_app.js +1 -0
  46. package/packages/web/.next/server/pages/_app.js.nft.json +1 -0
  47. package/packages/web/.next/server/pages/_document.js +1 -0
  48. package/packages/web/.next/server/pages/_document.js.nft.json +1 -0
  49. package/packages/web/.next/server/pages/_error.js +19 -0
  50. package/packages/web/.next/server/pages/_error.js.nft.json +1 -0
  51. package/packages/web/.next/server/pages-manifest.json +6 -1
  52. package/packages/web/.next/server/server-reference-manifest.js +1 -1
  53. package/packages/web/.next/server/server-reference-manifest.json +1 -5
  54. package/packages/web/.next/server/webpack-runtime.js +1 -209
  55. package/packages/web/.next/static/2XIFCTTKVZwN_RsNE-Rrr/_buildManifest.js +1 -0
  56. package/packages/web/.next/static/2XIFCTTKVZwN_RsNE-Rrr/_ssgManifest.js +1 -0
  57. package/packages/web/.next/static/chunks/255-0dc49b7a6e8e5c05.js +1 -0
  58. package/packages/web/.next/static/chunks/4bd1b696-382748cc942d8a14.js +1 -0
  59. package/packages/web/.next/static/chunks/app/_not-found/page-0da542be7eb33a64.js +1 -0
  60. package/packages/web/.next/static/chunks/app/layout-28a489fb4398663f.js +1 -0
  61. package/packages/web/.next/static/chunks/app/page-e58ccdb78625bce6.js +1 -0
  62. package/packages/web/.next/static/chunks/framework-ac73abd125e371fe.js +1 -0
  63. package/packages/web/.next/static/chunks/main-app-dd261207182e5a23.js +1 -0
  64. package/packages/web/.next/static/chunks/main-ee293fa6aa18bdd1.js +1 -0
  65. package/packages/web/.next/static/chunks/pages/_app-7d307437aca18ad4.js +1 -0
  66. package/packages/web/.next/static/chunks/pages/_error-cb2a52f75f2162e2.js +1 -0
  67. package/packages/web/.next/static/chunks/webpack-e1ae44446e7f7355.js +1 -0
  68. package/packages/web/.next/static/css/21d69157e271f2ab.css +3 -0
  69. package/packages/web/.next/trace +2 -5
  70. package/packages/web/app/page.tsx +5 -2
  71. package/packages/web/.next/server/vendor-chunks/@swc.js +0 -55
  72. package/packages/web/.next/server/vendor-chunks/next.js +0 -3010
  73. package/packages/web/.next/static/chunks/app/layout.js +0 -39
  74. package/packages/web/.next/static/chunks/app/page.js +0 -61
  75. package/packages/web/.next/static/chunks/app-pages-internals.js +0 -182
  76. package/packages/web/.next/static/chunks/main-app.js +0 -1882
  77. package/packages/web/.next/static/chunks/webpack.js +0 -1393
  78. package/packages/web/.next/static/css/app/layout.css +0 -1237
  79. package/packages/web/.next/static/development/_buildManifest.js +0 -1
  80. package/packages/web/.next/static/development/_ssgManifest.js +0 -1
  81. package/packages/web/.next/static/webpack/633457081244afec._.hot-update.json +0 -1
  82. package/packages/web/.next/static/webpack/6fee6306e0f98869.webpack.hot-update.json +0 -1
  83. package/packages/web/.next/static/webpack/73e341375c8d429e.webpack.hot-update.json +0 -1
  84. package/packages/web/.next/static/webpack/app/layout.6fee6306e0f98869.hot-update.js +0 -22
  85. package/packages/web/.next/static/webpack/app/layout.73e341375c8d429e.hot-update.js +0 -22
  86. package/packages/web/.next/static/webpack/app/page.6fee6306e0f98869.hot-update.js +0 -22
  87. package/packages/web/.next/static/webpack/app/page.73e341375c8d429e.hot-update.js +0 -22
  88. package/packages/web/.next/static/webpack/webpack.6fee6306e0f98869.hot-update.js +0 -12
  89. package/packages/web/.next/static/webpack/webpack.73e341375c8d429e.hot-update.js +0 -12
  90. /package/packages/web/.next/static/chunks/{polyfills.js → polyfills-42372ed130431b0a.js} +0 -0
@@ -1,10 +1,161 @@
1
- import { getVersions } from './contract';
1
+ import { getVersions, getSafestVersion, getAuthorByENS } from './contract';
2
+ import { resolveAddress } from './ens';
3
+ import { queryOSV, getFixedVersion, type OSVVulnerability } from './osv';
4
+
5
+ export interface ResolvedVersion {
6
+ version: string;
7
+ source: 'explicit' | 'latest' | 'ens' | 'auto-bumped';
8
+ ensName?: string;
9
+ authorAddress?: string;
10
+ reason?: string;
11
+ originalVersion?: string;
12
+ }
13
+
14
+ export function isENSVersion(version: string): boolean {
15
+ return version.endsWith('.eth');
16
+ }
17
+
18
+ export async function resolveVersion(
19
+ name: string,
20
+ version: string,
21
+ onStatus?: (msg: string) => void,
22
+ ): Promise<ResolvedVersion> {
23
+ const log = onStatus || (() => {});
24
+
25
+ if (isENSVersion(version)) {
26
+ return resolveENSVersion(name, version, log);
27
+ }
28
+
29
+ if (version && version !== 'latest') {
30
+ return { version, source: 'explicit' };
31
+ }
2
32
 
3
- export async function resolveVersion(name: string, version: string): Promise<string> {
4
- if (version && version !== 'latest') return version;
5
33
  try {
6
34
  const versions = await getVersions(name);
7
- if (versions.length > 0) return versions[versions.length - 1];
35
+ if (versions.length > 0) {
36
+ return { version: versions[versions.length - 1], source: 'latest' };
37
+ }
8
38
  } catch { /* no versions on-chain */ }
9
- return version;
39
+
40
+ const npmVersion = await resolveNpmLatest(name);
41
+ return { version: npmVersion, source: 'latest' };
42
+ }
43
+
44
+ async function resolveENSVersion(
45
+ packageName: string,
46
+ ensName: string,
47
+ log: (msg: string) => void,
48
+ ): Promise<ResolvedVersion> {
49
+ log(`Resolving ENS: ${ensName}`);
50
+ const authorAddr = await resolveAddress(ensName);
51
+ if (!authorAddr) {
52
+ throw new Error(`Cannot resolve ENS name: ${ensName}`);
53
+ }
54
+ log(`Address: ${authorAddr.slice(0, 6)}...${authorAddr.slice(-4)}`);
55
+
56
+ let authorOnChain = false;
57
+ try {
58
+ const profile = await getAuthorByENS(ensName);
59
+ authorOnChain = profile.addr !== '0x0000000000000000000000000000000000000000';
60
+ } catch { /* not registered */ }
61
+
62
+ if (!authorOnChain) {
63
+ throw new Error(`Author ${ensName} (${authorAddr.slice(0, 10)}...) is not registered on-chain`);
64
+ }
65
+ log(`Author verified on-chain ✓`);
66
+
67
+ let safestVersion: string | null = null;
68
+ try {
69
+ safestVersion = await getSafestVersion(packageName);
70
+ } catch { /* no on-chain versions */ }
71
+
72
+ if (safestVersion) {
73
+ log(`Safest on-chain version: ${safestVersion}`);
74
+ return {
75
+ version: safestVersion,
76
+ source: 'ens',
77
+ ensName,
78
+ authorAddress: authorAddr,
79
+ reason: `Safest on-chain version, author ${ensName} verified`,
80
+ };
81
+ }
82
+
83
+ log(`No on-chain scores, resolving latest from npm`);
84
+ const npmVersion = await resolveNpmLatest(packageName);
85
+ log(`Latest npm version: ${npmVersion}`);
86
+ return {
87
+ version: npmVersion,
88
+ source: 'ens',
89
+ ensName,
90
+ authorAddress: authorAddr,
91
+ reason: `Author ${ensName} verified, latest npm version (no on-chain scores)`,
92
+ };
93
+ }
94
+
95
+ export async function findSafeVersion(
96
+ name: string,
97
+ unsafeVersion: string,
98
+ cves: OSVVulnerability[],
99
+ ): Promise<ResolvedVersion | null> {
100
+ let safeVer: string | null = null;
101
+
102
+ try {
103
+ safeVer = await getSafestVersion(name);
104
+ } catch { /* no on-chain data */ }
105
+
106
+ if (safeVer && safeVer !== unsafeVersion) {
107
+ const safeCves = await queryOSV(name, safeVer).catch(() => []);
108
+ const hasCritical = safeCves.some((c) => {
109
+ const sev = c.database_specific?.severity || '';
110
+ return sev === 'CRITICAL' || sev === 'HIGH';
111
+ });
112
+ if (!hasCritical) {
113
+ return {
114
+ version: safeVer,
115
+ source: 'auto-bumped',
116
+ originalVersion: unsafeVersion,
117
+ reason: `On-chain safest version (original ${unsafeVersion} has vulnerabilities)`,
118
+ };
119
+ }
120
+ }
121
+
122
+ let bestFix: string | null = null;
123
+ for (const cve of cves) {
124
+ const fix = getFixedVersion(cve, unsafeVersion);
125
+ if (fix && (!bestFix || compareSemver(fix, bestFix) > 0)) {
126
+ bestFix = fix;
127
+ }
128
+ }
129
+
130
+ if (bestFix) {
131
+ return {
132
+ version: bestFix,
133
+ source: 'auto-bumped',
134
+ originalVersion: unsafeVersion,
135
+ reason: `Upgraded from ${unsafeVersion} to fix ${cves.length} CVE(s)`,
136
+ };
137
+ }
138
+
139
+ return null;
140
+ }
141
+
142
+ async function resolveNpmLatest(name: string): Promise<string> {
143
+ try {
144
+ const res = await fetch(`https://registry.npmjs.org/${encodeURIComponent(name)}/latest`);
145
+ if (res.ok) {
146
+ const data = await res.json() as { version?: string };
147
+ if (data.version) return data.version;
148
+ }
149
+ } catch { /* npm registry unreachable */ }
150
+ return 'latest';
151
+ }
152
+
153
+ function compareSemver(a: string, b: string): number {
154
+ const pa = a.replace(/^v/, '').split('.').map(Number);
155
+ const pb = b.replace(/^v/, '').split('.').map(Number);
156
+ for (let i = 0; i < 3; i++) {
157
+ const diff = (pa[i] || 0) - (pb[i] || 0);
158
+ if (diff !== 0) return diff;
159
+ }
160
+ return 0;
10
161
  }
@@ -45,6 +45,141 @@ export function validateScanResult(obj: unknown): obj is AgentScanResult {
45
45
  );
46
46
  }
47
47
 
48
+ const VALID_RISK_LEVELS = ['LOW', 'MEDIUM', 'HIGH', 'CRITICAL'] as const;
49
+ const VALID_RECOMMENDATIONS = ['SAFE', 'CAUTION', 'WARN', 'BLOCK'] as const;
50
+ const SCORE_KEYS = ['risk_score', 'score', 'riskScore', 'risk_rating'];
51
+ const LEVEL_KEYS = ['risk_level', 'riskLevel', 'level', 'severity', 'verdict', 'rating'];
52
+ const TEXT_KEYS = ['reasoning', 'summary', 'explanation', 'description', 'analysis', 'one_line_summary', 'one_liner'];
53
+
54
+ function deepFind(obj: Record<string, any>, keys: string[], type: 'number' | 'string', depth = 0): any {
55
+ if (depth > 4 || !obj || typeof obj !== 'object') return undefined;
56
+ for (const key of keys) {
57
+ const val = obj[key];
58
+ if (val !== undefined && val !== null) {
59
+ if (type === 'number') {
60
+ if (typeof val === 'number') return val;
61
+ if (typeof val === 'string' && !isNaN(parseFloat(val))) return parseFloat(val);
62
+ } else if (type === 'string' && typeof val === 'string' && val.length > 0) {
63
+ return val;
64
+ }
65
+ }
66
+ }
67
+ for (const key of Object.keys(obj)) {
68
+ const val = obj[key];
69
+ if (val && typeof val === 'object' && !Array.isArray(val)) {
70
+ const found = deepFind(val, keys, type, depth + 1);
71
+ if (found !== undefined) return found;
72
+ }
73
+ }
74
+ return undefined;
75
+ }
76
+
77
+ function deepFindArray(obj: Record<string, any>, keys: string[], depth = 0): any[] | undefined {
78
+ if (depth > 4 || !obj || typeof obj !== 'object') return undefined;
79
+ for (const key of keys) {
80
+ if (Array.isArray(obj[key])) return obj[key];
81
+ }
82
+ for (const key of Object.keys(obj)) {
83
+ const val = obj[key];
84
+ if (val && typeof val === 'object' && !Array.isArray(val)) {
85
+ const found = deepFindArray(val, keys, depth + 1);
86
+ if (found) return found;
87
+ }
88
+ }
89
+ return undefined;
90
+ }
91
+
92
+ function deepFindObj(obj: Record<string, any>, keys: string[], depth = 0): Record<string, any> | undefined {
93
+ if (depth > 3 || !obj || typeof obj !== 'object') return undefined;
94
+ for (const key of keys) {
95
+ const val = obj[key];
96
+ if (val && typeof val === 'object' && !Array.isArray(val)) return val;
97
+ }
98
+ return undefined;
99
+ }
100
+
101
+ function normalizeRiskLevel(val: unknown): RiskLevel {
102
+ if (typeof val !== 'string') return 'MEDIUM';
103
+ const upper = val.toUpperCase().trim();
104
+ if (VALID_RISK_LEVELS.includes(upper as RiskLevel)) return upper as RiskLevel;
105
+ if (upper === 'SAFE' || upper === 'NONE' || upper === 'INFO') return 'LOW';
106
+ if (upper === 'MODERATE' || upper === 'SUSPICIOUS') return 'MEDIUM';
107
+ if (upper === 'DANGEROUS' || upper === 'SEVERE') return 'CRITICAL';
108
+ return 'MEDIUM';
109
+ }
110
+
111
+ function normalizeRecommendation(val: unknown, riskLevel: RiskLevel): string {
112
+ if (typeof val === 'string') {
113
+ const upper = val.toUpperCase().trim();
114
+ if (VALID_RECOMMENDATIONS.includes(upper as any)) return upper;
115
+ }
116
+ const map: Record<RiskLevel, string> = { LOW: 'SAFE', MEDIUM: 'CAUTION', HIGH: 'WARN', CRITICAL: 'BLOCK' };
117
+ return map[riskLevel] || 'CAUTION';
118
+ }
119
+
120
+ /**
121
+ * Recursively searches an arbitrarily-shaped LLM response for risk_score,
122
+ * risk_level, reasoning, etc. and assembles a valid AgentScanResult.
123
+ */
124
+ export function normalizeScanResult(raw: unknown): AgentScanResult | null {
125
+ if (!raw || typeof raw !== 'object') return null;
126
+ const o = raw as Record<string, any>;
127
+
128
+ const riskScore = deepFind(o, SCORE_KEYS, 'number');
129
+ if (riskScore === undefined || isNaN(riskScore)) return null;
130
+
131
+ const rawLevel = deepFind(o, LEVEL_KEYS, 'string');
132
+ const riskLevel = normalizeRiskLevel(rawLevel);
133
+
134
+ const reasoning = deepFind(o, TEXT_KEYS, 'string') ?? `Risk score: ${riskScore}`;
135
+
136
+ const rawVulns = deepFindArray(o, ['vulnerabilities', 'findings', 'issues', 'alerts', 'concerns']);
137
+ const vulnerabilities = rawVulns
138
+ ? rawVulns.map((f: any) => ({
139
+ severity: normalizeRiskLevel(f.severity ?? f.level ?? f.risk_level),
140
+ category: f.category || f.type || f.issue || 'unknown',
141
+ description: f.description || f.message || f.detail || f.title || '',
142
+ file: f.file || f.location || f.path || '',
143
+ evidence: f.evidence || f.code || f.snippet || '',
144
+ }))
145
+ : [];
146
+
147
+ const sci = deepFindObj(o, ['supply_chain_indicators', 'supplyChainIndicators', 'indicators']);
148
+ const supply_chain_indicators = sci ?? {
149
+ has_install_scripts: false,
150
+ has_native_bindings: false,
151
+ has_obfuscated_code: false,
152
+ has_network_calls: false,
153
+ has_filesystem_access: false,
154
+ has_process_spawn: false,
155
+ has_eval_usage: false,
156
+ accesses_env_variables: false,
157
+ };
158
+
159
+ const va = deepFindObj(o, ['version_analysis', 'versionAnalysis']);
160
+ const version_analysis = va ?? {
161
+ version_reviewed: deepFind(o, ['version', 'version_reviewed'], 'string') ?? '',
162
+ previous_versions_reviewed: [],
163
+ changelog_risk: 'NONE',
164
+ changelog_reasoning: '',
165
+ };
166
+
167
+ const recommendation = normalizeRecommendation(
168
+ deepFind(o, ['recommendation', 'action', 'verdict'], 'string'),
169
+ riskLevel,
170
+ );
171
+
172
+ return {
173
+ risk_score: Math.max(0, Math.min(100, Math.round(riskScore))),
174
+ risk_level: riskLevel,
175
+ reasoning,
176
+ vulnerabilities,
177
+ supply_chain_indicators,
178
+ version_analysis,
179
+ recommendation: recommendation as any,
180
+ };
181
+ }
182
+
48
183
  export function safeJsonParse<T>(raw: string): T | null {
49
184
  try {
50
185
  return JSON.parse(raw) as T;
@@ -1,6 +1,6 @@
1
1
  import { OPENROUTER_API_URL, OPENAI_API_URL } from '@opm/core';
2
2
  import type { AgentScanResult } from '@opm/core';
3
- import { validateScanResult, safeJsonParse } from '@opm/core';
3
+ import { validateScanResult, normalizeScanResult, safeJsonParse } from '@opm/core';
4
4
 
5
5
  function getProvider(): { apiUrl: string; apiKey: string; kind: 'openai' | 'openrouter' } {
6
6
  const forcedProvider = process.env.LLM_PROVIDER;
@@ -53,6 +53,10 @@ export async function callLLM(
53
53
  headers['X-Title'] = 'OPM Security Scanner';
54
54
  }
55
55
 
56
+ const tokenLimit = kind === 'openai'
57
+ ? { max_completion_tokens: 4096 }
58
+ : { max_tokens: 4096 };
59
+
56
60
  const res = await fetch(apiUrl, {
57
61
  method: 'POST',
58
62
  headers,
@@ -64,7 +68,7 @@ export async function callLLM(
64
68
  ],
65
69
  response_format: { type: 'json_object' },
66
70
  temperature: 0.1,
67
- max_tokens: 4096,
71
+ ...tokenLimit,
68
72
  }),
69
73
  });
70
74
 
@@ -78,11 +82,14 @@ export async function callLLM(
78
82
  if (!raw) throw new Error(`Empty response from ${kind}/${model}`);
79
83
 
80
84
  const parsed = safeJsonParse<AgentScanResult>(raw);
81
- if (!parsed || !validateScanResult(parsed)) {
82
- throw new Error(`Invalid scan result JSON from ${model}: ${raw.slice(0, 200)}`);
83
- }
85
+ if (!parsed) throw new Error(`Unparseable JSON from ${model}: ${raw.slice(0, 200)}`);
84
86
 
85
- return parsed;
87
+ if (validateScanResult(parsed)) return parsed;
88
+
89
+ const normalized = normalizeScanResult(parsed);
90
+ if (!normalized) throw new Error(`Cannot normalize scan result from ${model}: ${raw.slice(0, 200)}`);
91
+
92
+ return normalized;
86
93
  }
87
94
 
88
95
  export async function callLLMRaw<T = unknown>(
@@ -102,6 +109,10 @@ export async function callLLMRaw<T = unknown>(
102
109
  headers['X-Title'] = 'OPM Security Scanner';
103
110
  }
104
111
 
112
+ const tokenLimit = kind === 'openai'
113
+ ? { max_completion_tokens: 4096 }
114
+ : { max_tokens: 4096 };
115
+
105
116
  const res = await fetch(apiUrl, {
106
117
  method: 'POST',
107
118
  headers,
@@ -113,7 +124,7 @@ export async function callLLMRaw<T = unknown>(
113
124
  ],
114
125
  response_format: { type: 'json_object' },
115
126
  temperature: 0.1,
116
- max_tokens: 4096,
127
+ ...tokenLimit,
117
128
  }),
118
129
  });
119
130
 
@@ -0,0 +1 @@
1
+ 2XIFCTTKVZwN_RsNE-Rrr
@@ -1,15 +1,26 @@
1
1
  {
2
2
  "pages": {
3
+ "/_not-found/page": [
4
+ "static/chunks/webpack-e1ae44446e7f7355.js",
5
+ "static/chunks/4bd1b696-382748cc942d8a14.js",
6
+ "static/chunks/255-0dc49b7a6e8e5c05.js",
7
+ "static/chunks/main-app-dd261207182e5a23.js",
8
+ "static/chunks/app/_not-found/page-0da542be7eb33a64.js"
9
+ ],
3
10
  "/layout": [
4
- "static/chunks/webpack.js",
5
- "static/chunks/main-app.js",
6
- "static/css/app/layout.css",
7
- "static/chunks/app/layout.js"
11
+ "static/chunks/webpack-e1ae44446e7f7355.js",
12
+ "static/chunks/4bd1b696-382748cc942d8a14.js",
13
+ "static/chunks/255-0dc49b7a6e8e5c05.js",
14
+ "static/chunks/main-app-dd261207182e5a23.js",
15
+ "static/css/21d69157e271f2ab.css",
16
+ "static/chunks/app/layout-28a489fb4398663f.js"
8
17
  ],
9
18
  "/page": [
10
- "static/chunks/webpack.js",
11
- "static/chunks/main-app.js",
12
- "static/chunks/app/page.js"
19
+ "static/chunks/webpack-e1ae44446e7f7355.js",
20
+ "static/chunks/4bd1b696-382748cc942d8a14.js",
21
+ "static/chunks/255-0dc49b7a6e8e5c05.js",
22
+ "static/chunks/main-app-dd261207182e5a23.js",
23
+ "static/chunks/app/page-e58ccdb78625bce6.js"
13
24
  ]
14
25
  }
15
26
  }
@@ -0,0 +1,4 @@
1
+ {
2
+ "/_not-found/page": "/_not-found",
3
+ "/page": "/"
4
+ }
@@ -1,20 +1,33 @@
1
1
  {
2
2
  "polyfillFiles": [
3
- "static/chunks/polyfills.js"
3
+ "static/chunks/polyfills-42372ed130431b0a.js"
4
4
  ],
5
5
  "devFiles": [],
6
6
  "ampDevFiles": [],
7
7
  "lowPriorityFiles": [
8
- "static/development/_buildManifest.js",
9
- "static/development/_ssgManifest.js"
8
+ "static/2XIFCTTKVZwN_RsNE-Rrr/_buildManifest.js",
9
+ "static/2XIFCTTKVZwN_RsNE-Rrr/_ssgManifest.js"
10
10
  ],
11
11
  "rootMainFiles": [
12
- "static/chunks/webpack.js",
13
- "static/chunks/main-app.js"
12
+ "static/chunks/webpack-e1ae44446e7f7355.js",
13
+ "static/chunks/4bd1b696-382748cc942d8a14.js",
14
+ "static/chunks/255-0dc49b7a6e8e5c05.js",
15
+ "static/chunks/main-app-dd261207182e5a23.js"
14
16
  ],
15
17
  "rootMainFilesTree": {},
16
18
  "pages": {
17
- "/_app": []
19
+ "/_app": [
20
+ "static/chunks/webpack-e1ae44446e7f7355.js",
21
+ "static/chunks/framework-ac73abd125e371fe.js",
22
+ "static/chunks/main-ee293fa6aa18bdd1.js",
23
+ "static/chunks/pages/_app-7d307437aca18ad4.js"
24
+ ],
25
+ "/_error": [
26
+ "static/chunks/webpack-e1ae44446e7f7355.js",
27
+ "static/chunks/framework-ac73abd125e371fe.js",
28
+ "static/chunks/main-ee293fa6aa18bdd1.js",
29
+ "static/chunks/pages/_error-cb2a52f75f2162e2.js"
30
+ ]
18
31
  },
19
32
  "ampFirstPages": []
20
33
  }
@@ -0,0 +1,6 @@
1
+ {
2
+ "buildStage": "static-generation",
3
+ "buildOptions": {
4
+ "useBuildWorker": "true"
5
+ }
6
+ }
@@ -0,0 +1 @@
1
+ {"name":"Next.js","version":"15.5.12"}
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 1,
3
+ "hasExportPathMap": false,
4
+ "exportTrailingSlash": false,
5
+ "isNextImageImported": false
6
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "version": 1,
3
+ "images": {
4
+ "deviceSizes": [
5
+ 640,
6
+ 750,
7
+ 828,
8
+ 1080,
9
+ 1200,
10
+ 1920,
11
+ 2048,
12
+ 3840
13
+ ],
14
+ "imageSizes": [
15
+ 16,
16
+ 32,
17
+ 48,
18
+ 64,
19
+ 96,
20
+ 128,
21
+ 256,
22
+ 384
23
+ ],
24
+ "path": "/_next/image",
25
+ "loader": "default",
26
+ "loaderFile": "",
27
+ "domains": [],
28
+ "disableStaticImages": false,
29
+ "minimumCacheTTL": 60,
30
+ "formats": [
31
+ "image/webp"
32
+ ],
33
+ "maximumResponseBody": 50000000,
34
+ "dangerouslyAllowSVG": false,
35
+ "contentSecurityPolicy": "script-src 'none'; frame-src 'none'; sandbox;",
36
+ "contentDispositionType": "attachment",
37
+ "remotePatterns": [],
38
+ "unoptimized": false,
39
+ "sizes": [
40
+ 640,
41
+ 750,
42
+ 828,
43
+ 1080,
44
+ 1200,
45
+ 1920,
46
+ 2048,
47
+ 3840,
48
+ 16,
49
+ 32,
50
+ 48,
51
+ 64,
52
+ 96,
53
+ 128,
54
+ 256,
55
+ 384
56
+ ]
57
+ }
58
+ }
@@ -0,0 +1 @@
1
+ {"version":1,"files":["../node_modules/@swc/helpers/_/_interop_require_default/package.json","../node_modules/@swc/helpers/cjs/_interop_require_default.cjs","../node_modules/@swc/helpers/package.json","../node_modules/client-only/index.js","../node_modules/client-only/package.json","../node_modules/next/dist/client/components/app-router-headers.js","../node_modules/next/dist/compiled/@opentelemetry/api/index.js","../node_modules/next/dist/compiled/@opentelemetry/api/package.json","../node_modules/next/dist/compiled/babel-code-frame/index.js","../node_modules/next/dist/compiled/babel-code-frame/package.json","../node_modules/next/dist/compiled/babel/code-frame.js","../node_modules/next/dist/compiled/babel/package.json","../node_modules/next/dist/compiled/bytes/index.js","../node_modules/next/dist/compiled/bytes/package.json","../node_modules/next/dist/compiled/next-server/server.runtime.prod.js","../node_modules/next/dist/compiled/source-map/package.json","../node_modules/next/dist/compiled/source-map/source-map.js","../node_modules/next/dist/compiled/stacktrace-parser/package.json","../node_modules/next/dist/compiled/stacktrace-parser/stack-trace-parser.cjs.js","../node_modules/next/dist/compiled/ws/index.js","../node_modules/next/dist/compiled/ws/package.json","../node_modules/next/dist/experimental/testmode/context.js","../node_modules/next/dist/experimental/testmode/fetch.js","../node_modules/next/dist/experimental/testmode/server-edge.js","../node_modules/next/dist/lib/client-and-server-references.js","../node_modules/next/dist/lib/constants.js","../node_modules/next/dist/lib/interop-default.js","../node_modules/next/dist/lib/is-error.js","../node_modules/next/dist/lib/picocolors.js","../node_modules/next/dist/next-devtools/server/shared.js","../node_modules/next/dist/server/after/builtin-request-context.js","../node_modules/next/dist/server/app-render/after-task-async-storage-instance.js","../node_modules/next/dist/server/app-render/after-task-async-storage.external.js","../node_modules/next/dist/server/app-render/async-local-storage.js","../node_modules/next/dist/server/app-render/work-async-storage-instance.js","../node_modules/next/dist/server/app-render/work-async-storage.external.js","../node_modules/next/dist/server/app-render/work-unit-async-storage-instance.js","../node_modules/next/dist/server/app-render/work-unit-async-storage.external.js","../node_modules/next/dist/server/body-streams.js","../node_modules/next/dist/server/lib/cache-handlers/default.external.js","../node_modules/next/dist/server/lib/incremental-cache/memory-cache.external.js","../node_modules/next/dist/server/lib/incremental-cache/shared-cache-controls.external.js","../node_modules/next/dist/server/lib/incremental-cache/tags-manifest.external.js","../node_modules/next/dist/server/lib/lru-cache.js","../node_modules/next/dist/server/lib/parse-stack.js","../node_modules/next/dist/server/lib/router-utils/instrumentation-globals.external.js","../node_modules/next/dist/server/lib/router-utils/instrumentation-node-extensions.js","../node_modules/next/dist/server/lib/router-utils/router-server-context.js","../node_modules/next/dist/server/lib/source-maps.js","../node_modules/next/dist/server/lib/trace/constants.js","../node_modules/next/dist/server/lib/trace/tracer.js","../node_modules/next/dist/server/load-manifest.external.js","../node_modules/next/dist/server/patch-error-inspect.js","../node_modules/next/dist/server/response-cache/types.js","../node_modules/next/dist/server/route-modules/app-page/module.compiled.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/amp-context.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/app-router-context.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/entrypoints.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/head-manager-context.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/hooks-client-context.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/image-config-context.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/router-context.js","../node_modules/next/dist/server/route-modules/app-page/vendored/contexts/server-inserted-html.js","../node_modules/next/dist/server/route-modules/pages/module.compiled.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/amp-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/app-router-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/entrypoints.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/head-manager-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/hooks-client-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/html-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/image-config-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/loadable-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/loadable.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/router-context.js","../node_modules/next/dist/server/route-modules/pages/vendored/contexts/server-inserted-html.js","../node_modules/next/dist/server/web/utils.js","../node_modules/next/dist/shared/lib/constants.js","../node_modules/next/dist/shared/lib/deep-freeze.js","../node_modules/next/dist/shared/lib/error-source.js","../node_modules/next/dist/shared/lib/invariant-error.js","../node_modules/next/dist/shared/lib/is-internal.js","../node_modules/next/dist/shared/lib/is-plain-object.js","../node_modules/next/dist/shared/lib/is-thenable.js","../node_modules/next/dist/shared/lib/modern-browserslist-target.js","../node_modules/next/dist/shared/lib/no-fallback-error.external.js","../node_modules/next/dist/shared/lib/runtime-config.external.js","../node_modules/next/dist/shared/lib/server-reference-info.js","../node_modules/next/package.json","../node_modules/react/cjs/react.production.js","../node_modules/react/index.js","../node_modules/react/package.json","../node_modules/styled-jsx/dist/index/index.js","../node_modules/styled-jsx/index.js","../node_modules/styled-jsx/package.json","../node_modules/styled-jsx/style.js","package.json"]}