easyeda-mcp-pro 0.35.3 → 0.35.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.
package/README.md CHANGED
@@ -42,8 +42,9 @@
42
42
  </a>
43
43
  </p>
44
44
 
45
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/oaslananka/easyeda-mcp-pro)
46
+
45
47
  <p>
46
- <a href="https://deepwiki.com/oaslananka/easyeda-mcp-pro">Ask DeepWiki</a> ·
47
48
  <a href="docs/ROADMAP.md">Roadmap</a> ·
48
49
  <a href="docs/OPENSSF_BEST_PRACTICES.md">OpenSSF evidence</a> ·
49
50
  <a href="docs/SECURITY_ASSURANCE_CASE.md">Security assurance case</a>
@@ -1 +1 @@
1
- export declare const SERVER_VERSION = "0.35.3";
1
+ export declare const SERVER_VERSION = "0.35.4";
@@ -1,2 +1,2 @@
1
- export const SERVER_VERSION = '0.35.3'; // x-release-please-version
1
+ export const SERVER_VERSION = '0.35.4'; // x-release-please-version
2
2
  //# sourceMappingURL=version.js.map
@@ -0,0 +1,96 @@
1
+ export declare function sortUnknownForStableHash(value: unknown): unknown;
2
+ export declare function extractPrimitiveId(value: unknown): string | undefined;
3
+ export declare function primitiveDescriptorHash(snapshot: unknown): string;
4
+ export declare function extractPrimitiveIds(value: unknown): string[];
5
+ export interface SchematicTransactionFixtureIdentity {
6
+ project: string;
7
+ schematic: string;
8
+ page: string;
9
+ disposable: true;
10
+ }
11
+ export interface SchematicTransactionRuntimeIdentity {
12
+ projectInfo: unknown;
13
+ schematicInfo: unknown;
14
+ pageInfo: unknown;
15
+ }
16
+ export interface SchematicTransactionFixtureMismatch {
17
+ field: 'project' | 'schematic' | 'page';
18
+ expected: string;
19
+ actual?: string;
20
+ }
21
+ export declare function verifySchematicTransactionFixtureIdentity(expected: SchematicTransactionFixtureIdentity, runtime: SchematicTransactionRuntimeIdentity): {
22
+ ok: boolean;
23
+ actual: {
24
+ project?: string;
25
+ schematic?: string;
26
+ page?: string;
27
+ };
28
+ mismatches: SchematicTransactionFixtureMismatch[];
29
+ };
30
+ export interface SchematicTransactionStateDigest {
31
+ primitiveInventoryHash: string;
32
+ componentHash: string;
33
+ netHash: string;
34
+ ercAvailable: boolean;
35
+ ercHash?: string;
36
+ }
37
+ export interface SchematicTransactionOutcome {
38
+ passed: boolean;
39
+ rolledBack: boolean;
40
+ stateRestored: boolean;
41
+ details?: Record<string, unknown>;
42
+ }
43
+ export interface SchematicTransactionSmokeInput {
44
+ generatedAt?: string;
45
+ environment: {
46
+ operatingSystem: string;
47
+ architecture: string;
48
+ nodeVersion: string;
49
+ };
50
+ fixture: SchematicTransactionFixtureIdentity;
51
+ bridge: {
52
+ easyedaVersion?: string;
53
+ bridgeVersion?: string;
54
+ dispatcherBuildId?: string;
55
+ methodRegistryHash?: string;
56
+ activePort?: number;
57
+ };
58
+ outcomes: {
59
+ createRollback: SchematicTransactionOutcome;
60
+ modifyRollback: SchematicTransactionOutcome;
61
+ deleteRollback: SchematicTransactionOutcome;
62
+ };
63
+ cleanup: {
64
+ remainingIds: string[];
65
+ errors: string[];
66
+ };
67
+ baseline: SchematicTransactionStateDigest;
68
+ finalState: SchematicTransactionStateDigest;
69
+ error?: string;
70
+ }
71
+ export type SchematicTransactionSmokeCheckId = 'create-rollback' | 'modify-rollback' | 'delete-rollback' | 'final-state-restored';
72
+ export interface SchematicTransactionSmokeCheck {
73
+ id: SchematicTransactionSmokeCheckId;
74
+ status: 'passed' | 'failed';
75
+ details: Record<string, unknown>;
76
+ }
77
+ export interface SchematicTransactionSmokeReport {
78
+ schemaVersion: 1;
79
+ status: 'passed' | 'failed';
80
+ generatedAt: string;
81
+ environment: SchematicTransactionSmokeInput['environment'];
82
+ fixture: SchematicTransactionFixtureIdentity;
83
+ bridge: SchematicTransactionSmokeInput['bridge'];
84
+ checks: SchematicTransactionSmokeCheck[];
85
+ cleanup: {
86
+ clean: boolean;
87
+ remainingIds: string[];
88
+ errors: string[];
89
+ };
90
+ baseline: SchematicTransactionStateDigest;
91
+ finalState: SchematicTransactionStateDigest;
92
+ error?: string;
93
+ }
94
+ export declare function compareSchematicTransactionState(baseline: SchematicTransactionStateDigest, finalState: SchematicTransactionStateDigest): Record<string, boolean>;
95
+ export declare function buildSchematicTransactionSmokeReport(input: SchematicTransactionSmokeInput): SchematicTransactionSmokeReport;
96
+ export declare function writeSchematicTransactionSmokeReport(path: string, report: SchematicTransactionSmokeReport): Promise<void>;
@@ -0,0 +1,160 @@
1
+ import { mkdir, rename, writeFile } from 'node:fs/promises';
2
+ import { dirname, resolve } from 'node:path';
3
+ import { stableHash } from '../transactions/stable.js';
4
+ export function sortUnknownForStableHash(value) {
5
+ if (Array.isArray(value)) {
6
+ return value
7
+ .map(sortUnknownForStableHash)
8
+ .sort((left, right) => JSON.stringify(left).localeCompare(JSON.stringify(right)));
9
+ }
10
+ if (value && typeof value === 'object') {
11
+ return Object.fromEntries(Object.entries(value)
12
+ .sort(([left], [right]) => left.localeCompare(right))
13
+ .map(([key, nested]) => [key, sortUnknownForStableHash(nested)]));
14
+ }
15
+ return value;
16
+ }
17
+ const PRIMITIVE_ID_KEYS = ['primitiveId', 'primitiveUuid', 'id', 'uuid'];
18
+ const PRIMITIVE_NESTED_KEYS = ['result', 'data', 'text', 'rectangle'];
19
+ export function extractPrimitiveId(value) {
20
+ if (typeof value === 'string')
21
+ return value.trim() || undefined;
22
+ if (Array.isArray(value)) {
23
+ for (const item of value) {
24
+ const id = extractPrimitiveId(item);
25
+ if (id)
26
+ return id;
27
+ }
28
+ return undefined;
29
+ }
30
+ if (!value || typeof value !== 'object')
31
+ return undefined;
32
+ const record = value;
33
+ for (const key of PRIMITIVE_ID_KEYS) {
34
+ const id = extractPrimitiveId(record[key]);
35
+ if (id)
36
+ return id;
37
+ }
38
+ for (const key of PRIMITIVE_NESTED_KEYS) {
39
+ const id = extractPrimitiveId(record[key]);
40
+ if (id)
41
+ return id;
42
+ }
43
+ return undefined;
44
+ }
45
+ export function primitiveDescriptorHash(snapshot) {
46
+ if (!snapshot || typeof snapshot !== 'object' || Array.isArray(snapshot)) {
47
+ return stableHash(snapshot);
48
+ }
49
+ const copy = structuredClone(snapshot);
50
+ delete copy.primitiveId;
51
+ return stableHash(copy);
52
+ }
53
+ export function extractPrimitiveIds(value) {
54
+ if (!value || typeof value !== 'object' || Array.isArray(value))
55
+ return [];
56
+ const primitiveIds = value.primitiveIds;
57
+ return Array.isArray(primitiveIds)
58
+ ? primitiveIds
59
+ .filter((id) => typeof id === 'string' && id.length > 0)
60
+ .sort((a, b) => a.localeCompare(b))
61
+ : [];
62
+ }
63
+ function recordString(value, keys) {
64
+ if (!value || typeof value !== 'object' || Array.isArray(value))
65
+ return undefined;
66
+ const record = value;
67
+ for (const key of keys) {
68
+ const candidate = record[key];
69
+ if (typeof candidate === 'string' && candidate.trim())
70
+ return candidate.trim();
71
+ }
72
+ return undefined;
73
+ }
74
+ export function verifySchematicTransactionFixtureIdentity(expected, runtime) {
75
+ const actual = {
76
+ project: recordString(runtime.projectInfo, ['friendlyName', 'name']),
77
+ schematic: recordString(runtime.schematicInfo, ['name']),
78
+ page: recordString(runtime.pageInfo, ['name']),
79
+ };
80
+ const mismatches = [];
81
+ for (const field of ['project', 'schematic', 'page']) {
82
+ if (actual[field] !== expected[field]) {
83
+ mismatches.push({
84
+ field,
85
+ expected: expected[field],
86
+ ...(actual[field] ? { actual: actual[field] } : {}),
87
+ });
88
+ }
89
+ }
90
+ return { ok: mismatches.length === 0, actual, mismatches };
91
+ }
92
+ function outcomeCheck(id, outcome) {
93
+ const passed = outcome.passed && outcome.rolledBack && outcome.stateRestored;
94
+ return {
95
+ id,
96
+ status: passed ? 'passed' : 'failed',
97
+ details: {
98
+ passed: outcome.passed,
99
+ rolledBack: outcome.rolledBack,
100
+ stateRestored: outcome.stateRestored,
101
+ ...(outcome.details ?? {}),
102
+ },
103
+ };
104
+ }
105
+ export function compareSchematicTransactionState(baseline, finalState) {
106
+ const ercComparable = baseline.ercAvailable && finalState.ercAvailable;
107
+ return {
108
+ primitiveInventoryHashEqual: baseline.primitiveInventoryHash === finalState.primitiveInventoryHash,
109
+ componentHashEqual: baseline.componentHash === finalState.componentHash,
110
+ netHashEqual: baseline.netHash === finalState.netHash,
111
+ ercComparable,
112
+ ercStateEqual: !ercComparable || baseline.ercHash === finalState.ercHash,
113
+ };
114
+ }
115
+ export function buildSchematicTransactionSmokeReport(input) {
116
+ const finalComparison = compareSchematicTransactionState(input.baseline, input.finalState);
117
+ const finalStatePassed = finalComparison.primitiveInventoryHashEqual &&
118
+ finalComparison.componentHashEqual &&
119
+ finalComparison.netHashEqual &&
120
+ finalComparison.ercStateEqual;
121
+ const checks = [
122
+ outcomeCheck('create-rollback', input.outcomes.createRollback),
123
+ outcomeCheck('modify-rollback', input.outcomes.modifyRollback),
124
+ outcomeCheck('delete-rollback', input.outcomes.deleteRollback),
125
+ {
126
+ id: 'final-state-restored',
127
+ status: finalStatePassed ? 'passed' : 'failed',
128
+ details: finalComparison,
129
+ },
130
+ ];
131
+ const cleanup = {
132
+ clean: input.cleanup.remainingIds.length === 0 && input.cleanup.errors.length === 0,
133
+ remainingIds: [...input.cleanup.remainingIds],
134
+ errors: [...input.cleanup.errors],
135
+ };
136
+ const status = checks.every((check) => check.status === 'passed') && cleanup.clean && !input.error
137
+ ? 'passed'
138
+ : 'failed';
139
+ return {
140
+ schemaVersion: 1,
141
+ status,
142
+ generatedAt: input.generatedAt ?? new Date().toISOString(),
143
+ environment: input.environment,
144
+ fixture: input.fixture,
145
+ bridge: input.bridge,
146
+ checks,
147
+ cleanup,
148
+ baseline: input.baseline,
149
+ finalState: input.finalState,
150
+ ...(input.error ? { error: input.error } : {}),
151
+ };
152
+ }
153
+ export async function writeSchematicTransactionSmokeReport(path, report) {
154
+ const absolutePath = resolve(path);
155
+ await mkdir(dirname(absolutePath), { recursive: true });
156
+ const temporaryPath = `${absolutePath}.${process.pid}.${Date.now()}.tmp`;
157
+ await writeFile(temporaryPath, `${JSON.stringify(report, null, 2)}\n`, 'utf8');
158
+ await rename(temporaryPath, absolutePath);
159
+ }
160
+ //# sourceMappingURL=schematic-transaction-smoke-report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schematic-transaction-smoke-report.js","sourceRoot":"","sources":["../../src/live/schematic-transaction-smoke-report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ export type ReleaseChannel = 'stable' | 'prerelease';
2
+ export type ProvenanceObservation = 'passed' | 'failed' | 'unverified';
3
+ export type ReleaseVerificationCheckStatus = 'passed' | 'failed';
4
+ export interface ReleaseVerificationExpectation {
5
+ repository: string;
6
+ packageName: string;
7
+ mcpName: string;
8
+ version: string;
9
+ tag: string;
10
+ channel: ReleaseChannel;
11
+ npmDistTag: string;
12
+ commitSha: string;
13
+ requiredAssets: string[];
14
+ requiredGhcrTags: string[];
15
+ }
16
+ export interface ReleaseAssetObservation {
17
+ name: string;
18
+ digest?: string;
19
+ }
20
+ export interface ReleaseVerificationObservation {
21
+ npm: {
22
+ version?: string;
23
+ distTags: Record<string, string | undefined>;
24
+ provenance: ProvenanceObservation;
25
+ workflowContextProof?: boolean;
26
+ };
27
+ github: {
28
+ tag?: string;
29
+ tagCommitSha?: string;
30
+ isDraft?: boolean;
31
+ isPrerelease?: boolean;
32
+ assets: ReleaseAssetObservation[];
33
+ };
34
+ ghcr: {
35
+ digest?: string;
36
+ tags: string[];
37
+ };
38
+ mcpRegistry: {
39
+ version?: string;
40
+ isLatest?: boolean;
41
+ } | null;
42
+ }
43
+ export type ReleaseVerificationCheckId = 'npm-version' | 'npm-dist-tag' | 'npm-provenance' | 'github-tag' | 'github-tag-commit' | 'github-classification' | 'github-assets' | 'ghcr-tags' | 'mcp-registry';
44
+ export interface ReleaseVerificationCheck {
45
+ id: ReleaseVerificationCheckId;
46
+ status: ReleaseVerificationCheckStatus;
47
+ expected: unknown;
48
+ actual: unknown;
49
+ message?: string;
50
+ }
51
+ export interface ReleaseVerificationReport {
52
+ ok: boolean;
53
+ checks: ReleaseVerificationCheck[];
54
+ failures: ReleaseVerificationCheck[];
55
+ }
56
+ export declare function verifyPublishedReleaseObservation(expectation: ReleaseVerificationExpectation, observation: ReleaseVerificationObservation): ReleaseVerificationReport;
@@ -0,0 +1,63 @@
1
+ function check(id, passed, expected, actual, message) {
2
+ return {
3
+ id,
4
+ status: passed ? 'passed' : 'failed',
5
+ expected,
6
+ actual,
7
+ ...(message ? { message } : {}),
8
+ };
9
+ }
10
+ function sortedUnique(values) {
11
+ return [...new Set(values)].sort((left, right) => left.localeCompare(right));
12
+ }
13
+ function sameStringSet(expected, actual) {
14
+ const normalizedExpected = sortedUnique(expected);
15
+ const normalizedActual = sortedUnique(actual);
16
+ return (normalizedExpected.length === normalizedActual.length &&
17
+ normalizedExpected.every((value, index) => value === normalizedActual[index]));
18
+ }
19
+ export function verifyPublishedReleaseObservation(expectation, observation) {
20
+ const expectedPrerelease = expectation.channel === 'prerelease';
21
+ const assetByName = new Map(observation.github.assets.map((asset) => [asset.name, asset]));
22
+ const missingOrUndigestedAssets = expectation.requiredAssets.filter((name) => {
23
+ const asset = assetByName.get(name);
24
+ return !asset || typeof asset.digest !== 'string' || asset.digest.trim().length === 0;
25
+ });
26
+ const provenancePassed = observation.npm.provenance === 'passed' || observation.npm.workflowContextProof === true;
27
+ const provenanceActual = {
28
+ registry: observation.npm.provenance,
29
+ workflowContextProof: observation.npm.workflowContextProof === true,
30
+ };
31
+ const ghcrDigestPresent = typeof observation.ghcr.digest === 'string' && observation.ghcr.digest.trim().length > 0;
32
+ const ghcrTagsMatch = sameStringSet(expectation.requiredGhcrTags, observation.ghcr.tags);
33
+ const mcpPassed = expectation.channel === 'stable'
34
+ ? observation.mcpRegistry?.version === expectation.version &&
35
+ observation.mcpRegistry?.isLatest === true
36
+ : observation.mcpRegistry === null;
37
+ const checks = [
38
+ check('npm-version', observation.npm.version === expectation.version, expectation.version, observation.npm.version, 'The exact npm package version must match the release version.'),
39
+ check('npm-dist-tag', observation.npm.distTags[expectation.npmDistTag] === expectation.version, { [expectation.npmDistTag]: expectation.version }, { [expectation.npmDistTag]: observation.npm.distTags[expectation.npmDistTag] }, 'The channel-specific npm dist-tag must point to the exact release version.'),
40
+ check('npm-provenance', provenancePassed, 'registry provenance passed or workflow-context proof present', provenanceActual, 'The npm package must have registry provenance or verified workflow-context proof.'),
41
+ check('github-tag', observation.github.tag === expectation.tag, expectation.tag, observation.github.tag, 'The GitHub Release tag must match the expected immutable release tag.'),
42
+ check('github-tag-commit', observation.github.tagCommitSha === expectation.commitSha, expectation.commitSha, observation.github.tagCommitSha, 'The release tag must resolve to the expected candidate commit.'),
43
+ check('github-classification', observation.github.isDraft === false &&
44
+ observation.github.isPrerelease === expectedPrerelease, { isDraft: false, isPrerelease: expectedPrerelease }, {
45
+ isDraft: observation.github.isDraft,
46
+ isPrerelease: observation.github.isPrerelease,
47
+ }, 'The GitHub Release draft/prerelease classification must match the channel.'),
48
+ check('github-assets', missingOrUndigestedAssets.length === 0, expectation.requiredAssets, observation.github.assets, missingOrUndigestedAssets.length > 0
49
+ ? `Missing or undigested assets: ${missingOrUndigestedAssets.join(', ')}`
50
+ : undefined),
51
+ check('ghcr-tags', ghcrDigestPresent && ghcrTagsMatch, { digest: 'non-empty', tags: sortedUnique(expectation.requiredGhcrTags) }, { digest: observation.ghcr.digest, tags: sortedUnique(observation.ghcr.tags) }, 'All exact and moving GHCR tags must resolve to one non-empty image digest.'),
52
+ check('mcp-registry', mcpPassed, expectation.channel === 'stable' ? { version: expectation.version, isLatest: true } : null, observation.mcpRegistry, expectation.channel === 'stable'
53
+ ? 'Stable releases must be present in the MCP Registry and marked latest.'
54
+ : 'Prereleases must not be published to the MCP Registry.'),
55
+ ];
56
+ const failures = checks.filter((item) => item.status === 'failed');
57
+ return {
58
+ ok: failures.length === 0,
59
+ checks,
60
+ failures,
61
+ };
62
+ }
63
+ //# sourceMappingURL=published-release-verifier.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"published-release-verifier.js","sourceRoot":"","sources":["../../src/release/published-release-verifier.ts"],"names":[],"mappings":"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"}
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "easyeda-mcp-pro",
3
- "version": "0.35.3",
3
+ "version": "0.35.4",
4
4
  "mcpName": "io.github.oaslananka/easyeda-mcp-pro",
5
5
  "description": "MCP server for EasyEDA Pro: PCB inspection, BOM, exports, and hardware review.",
6
6
  "keywords": [
@@ -112,7 +112,8 @@
112
112
  "generate:capability-docs": "tsx scripts/update-capability-counts.mts",
113
113
  "check:capability-docs": "tsx scripts/update-capability-counts.mts --check",
114
114
  "release:readiness": "node scripts/check-release-readiness.mjs",
115
- "release:readiness:compatibility": "node scripts/check-release-readiness.mjs --compatibility-only"
115
+ "release:readiness:compatibility": "node scripts/check-release-readiness.mjs --compatibility-only",
116
+ "release:verify-published": "node scripts/verify-published-release.mjs"
116
117
  },
117
118
  "dependencies": {
118
119
  "@modelcontextprotocol/sdk": "^1.29.0",