proofseal 0.0.2 → 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 (56) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE +13 -0
  3. package/README.md +204 -7
  4. package/dist/cli/index.d.ts +2 -0
  5. package/dist/cli/index.js +440 -0
  6. package/dist/cli/index.js.map +1 -0
  7. package/dist/config.d.ts +19 -0
  8. package/dist/config.js +58 -0
  9. package/dist/config.js.map +1 -0
  10. package/dist/core/canonical.d.ts +16 -0
  11. package/dist/core/canonical.js +29 -0
  12. package/dist/core/canonical.js.map +1 -0
  13. package/dist/core/hash.d.ts +32 -0
  14. package/dist/core/hash.js +81 -0
  15. package/dist/core/hash.js.map +1 -0
  16. package/dist/core/marker-lint.d.ts +5 -0
  17. package/dist/core/marker-lint.js +55 -0
  18. package/dist/core/marker-lint.js.map +1 -0
  19. package/dist/core/paths.d.ts +10 -0
  20. package/dist/core/paths.js +13 -0
  21. package/dist/core/paths.js.map +1 -0
  22. package/dist/harness/quantize.d.ts +38 -0
  23. package/dist/harness/quantize.js +76 -0
  24. package/dist/harness/quantize.js.map +1 -0
  25. package/dist/harness/run.d.ts +61 -0
  26. package/dist/harness/run.js +137 -0
  27. package/dist/harness/run.js.map +1 -0
  28. package/dist/history/gitinfo.d.ts +16 -0
  29. package/dist/history/gitinfo.js +69 -0
  30. package/dist/history/gitinfo.js.map +1 -0
  31. package/dist/history/jsonl.d.ts +28 -0
  32. package/dist/history/jsonl.js +71 -0
  33. package/dist/history/jsonl.js.map +1 -0
  34. package/dist/history/queries.d.ts +43 -0
  35. package/dist/history/queries.js +86 -0
  36. package/dist/history/queries.js.map +1 -0
  37. package/dist/index.d.ts +18 -0
  38. package/dist/index.js +19 -0
  39. package/dist/index.js.map +1 -0
  40. package/dist/keys/derive.d.ts +28 -0
  41. package/dist/keys/derive.js +59 -0
  42. package/dist/keys/derive.js.map +1 -0
  43. package/dist/manifest/schema.d.ts +1068 -0
  44. package/dist/manifest/schema.js +102 -0
  45. package/dist/manifest/schema.js.map +1 -0
  46. package/dist/manifest/seal.d.ts +41 -0
  47. package/dist/manifest/seal.js +185 -0
  48. package/dist/manifest/seal.js.map +1 -0
  49. package/dist/manifest/verify.d.ts +102 -0
  50. package/dist/manifest/verify.js +246 -0
  51. package/dist/manifest/verify.js.map +1 -0
  52. package/dist/mcp/server.d.ts +1 -0
  53. package/dist/mcp/server.js +138 -0
  54. package/dist/mcp/server.js.map +1 -0
  55. package/package.json +43 -13
  56. package/bin.js +0 -19
@@ -0,0 +1,246 @@
1
+ /**
2
+ * Verify — the stranger command. Integrity-seal triple-check (recompute
3
+ * hash, re-derive pubkey from embedded commit+salt, verify the seal) plus
4
+ * per-claim pass/drift/regressed/missing classification and the 0/1/2
5
+ * exit-code contract (D7, ported from ruflo verify.mjs / issue #1880).
6
+ */
7
+ import { existsSync } from 'node:fs';
8
+ import { readFileSync } from 'node:fs';
9
+ import { join, resolve } from 'node:path';
10
+ import { canonicalize } from '../core/canonical.js';
11
+ import { normalizeClaimPath } from '../core/paths.js';
12
+ import { sha256Hex, fileSha256, fileSha256CrlfNormalized, markerPresent as markerPresentIn, } from '../core/hash.js';
13
+ import { deriveKey, verifyBytes } from '../keys/derive.js';
14
+ import { runHarness } from '../harness/run.js';
15
+ import { loadConfig, DEFAULT_MANIFEST_PATH } from '../config.js';
16
+ export const THREAT_MODEL_NOTE = 'commit-bound tamper-evidence, not third-party authentication';
17
+ /** Detail attached to a regressed file-hash claim caused by git autocrlf. */
18
+ export const CRLF_DETAIL = 'content identical after line-ending normalization — likely git autocrlf; pin with .gitattributes (* text=auto eol=lf)';
19
+ /** Named precondition hint for an uncommitted reference vector (premortem #5). */
20
+ export const REFERENCE_VECTOR_HINT = 'reference vector not found — did you commit the seal outputs? (run `proofseal seal` then commit the listed files)';
21
+ /** Build-output path pattern: a missing file here usually means "not built". */
22
+ const BUILD_OUTPUT_RE = /(^|\/)(dist|build|out)\//;
23
+ /** Map a VerifyResult onto the pinned v1 JSON schema. */
24
+ export function toVerifyJson(r) {
25
+ return {
26
+ ok: r.ok,
27
+ signature: {
28
+ valid: r.signature.manifestHashOk && r.signature.publicKeyReproducible && r.signature.signatureValid,
29
+ publicKey: r.signature.publicKey,
30
+ publicKeyReproducible: r.signature.publicKeyReproducible,
31
+ },
32
+ summary: { totalClaims: r.results.length, ...r.summary },
33
+ results: r.results.map((c) => ({
34
+ id: c.id,
35
+ type: c.type,
36
+ status: c.status,
37
+ file: c.file ?? '',
38
+ detail: c.detail ?? '',
39
+ })),
40
+ precondition: r.precondition ? { reason: r.precondition, hint: r.hint ?? '' } : null,
41
+ ...(r.platformWarning ? { platformWarning: r.platformWarning } : {}),
42
+ };
43
+ }
44
+ /** Integrity-seal triple-check (ADR §5.4). */
45
+ export function checkSignature(witness) {
46
+ const recomputed = sha256Hex(canonicalize(witness.manifest));
47
+ const manifestHashOk = recomputed === witness.integrity.manifestHash;
48
+ const key = deriveKey(witness.manifest.gitCommit, witness.manifest.salt);
49
+ const publicKeyReproducible = key.publicKeyHex === witness.integrity.publicKey;
50
+ const signatureValid = verifyBytes(witness.integrity.publicKey, Buffer.from(witness.integrity.manifestHash, 'hex'), witness.integrity.signature);
51
+ return { manifestHashOk, publicKeyReproducible, signatureValid, publicKey: witness.integrity.publicKey };
52
+ }
53
+ /** Classify a file-backed (file-hash | marker) claim against the live tree. */
54
+ export function classifyFileClaim(root, claim) {
55
+ if (claim.type === 'harness') {
56
+ throw new Error('classifyFileClaim called with a harness claim');
57
+ }
58
+ // Windows insurance: tolerate manifests sealed with backslash paths.
59
+ const file = normalizeClaimPath(claim.file);
60
+ const base = { id: claim.id, type: claim.type, desc: claim.desc, file };
61
+ const abs = join(root, file);
62
+ if (!existsSync(abs)) {
63
+ return { ...base, status: 'missing', sha256Match: false, markerPresent: false };
64
+ }
65
+ const localSha256 = fileSha256(abs);
66
+ const sha256Match = localSha256 === claim.sha256;
67
+ if (claim.type === 'file-hash') {
68
+ // The hash IS the expectation: mismatch = regressed (no drift slot).
69
+ if (sha256Match)
70
+ return { ...base, status: 'pass', sha256Match, localSha256 };
71
+ // CRLF-aware detail (premortem #7): bytes are the contract, so the
72
+ // classification STAYS regressed — but when the CRLF→LF-normalized
73
+ // content matches the sealed hash, the detail names git autocrlf.
74
+ const crlfDetail = fileSha256CrlfNormalized(abs) === claim.sha256 ? CRLF_DETAIL : undefined;
75
+ return { ...base, status: 'regressed', sha256Match, localSha256, ...(crlfDetail ? { detail: crlfDetail } : {}) };
76
+ }
77
+ // Whitespace-normalized (premortem #7): re-indents/line-wraps of the
78
+ // marker's surroundings are drift, not a false regression.
79
+ const markerPresent = markerPresentIn(readFileSync(abs, 'utf8'), claim.marker);
80
+ const status = sha256Match && markerPresent ? 'pass' : markerPresent ? 'drift' : 'regressed';
81
+ return { ...base, status, sha256Match, markerPresent, localSha256 };
82
+ }
83
+ async function classifyHarnessClaim(root, claim) {
84
+ if (claim.type !== 'harness')
85
+ throw new Error('expected harness claim');
86
+ const base = { id: claim.id, type: claim.type, desc: claim.desc };
87
+ const result = await runHarness({
88
+ name: claim.harness,
89
+ cmd: claim.cmd,
90
+ cwd: root,
91
+ seed: claim.seed,
92
+ quantizeDecimals: claim.quantizeDecimals,
93
+ exclude: claim.exclude,
94
+ expectedSha256: claim.expectedSha256,
95
+ referenceVector: claim.referenceVector ? normalizeClaimPath(claim.referenceVector) : undefined,
96
+ tolerance: claim.tolerance,
97
+ });
98
+ const status = result.status === 'error' || result.status === 'missing' ? 'missing' : result.status;
99
+ return {
100
+ ...base,
101
+ status,
102
+ hashMatch: result.hashMatch,
103
+ toleranceMatch: result.toleranceMatch,
104
+ detail: result.commandNotFound
105
+ ? `precondition-suspect: harness command not found (${claim.cmd}) — is the environment set up?`
106
+ : result.error,
107
+ ...(result.commandNotFound ? { preconditionSuspect: true } : {}),
108
+ ...(result.referenceVectorMissing ? { referenceVectorMissing: true } : {}),
109
+ };
110
+ }
111
+ function summarize(results) {
112
+ return {
113
+ pass: results.filter((r) => r.status === 'pass').length,
114
+ drift: results.filter((r) => r.status === 'drift').length,
115
+ regressed: results.filter((r) => r.status === 'regressed').length,
116
+ missing: results.filter((r) => r.status === 'missing').length,
117
+ };
118
+ }
119
+ const EMPTY_SIG = {
120
+ manifestHashOk: false,
121
+ publicKeyReproducible: false,
122
+ signatureValid: false,
123
+ publicKey: '',
124
+ };
125
+ function precondition(reason, hint, summary, signature, results) {
126
+ return {
127
+ ok: false,
128
+ exitCode: 2,
129
+ precondition: reason,
130
+ hint,
131
+ signature: signature ?? EMPTY_SIG,
132
+ summary: summary ?? { pass: 0, drift: 0, regressed: 0, missing: 0 },
133
+ results: results ?? [],
134
+ note: THREAT_MODEL_NOTE,
135
+ };
136
+ }
137
+ function resolveManifestPath(opts) {
138
+ const root = resolve(opts.root ?? process.cwd());
139
+ if (opts.manifestPath)
140
+ return { root, manifestPath: resolve(opts.manifestPath) };
141
+ try {
142
+ const cfg = loadConfig(root);
143
+ return { root, manifestPath: cfg.manifestPath };
144
+ }
145
+ catch {
146
+ return { root, manifestPath: join(root, DEFAULT_MANIFEST_PATH) };
147
+ }
148
+ }
149
+ /** Verify a sealed manifest against the live tree. Never throws on bad repos. */
150
+ export async function verify(opts = {}) {
151
+ const { root, manifestPath } = resolveManifestPath(opts);
152
+ if (!existsSync(manifestPath)) {
153
+ return precondition('manifest-not-found', `no sealed manifest at ${manifestPath} — run \`proofseal seal\` first`);
154
+ }
155
+ let witness;
156
+ try {
157
+ witness = JSON.parse(readFileSync(manifestPath, 'utf8'));
158
+ if (!witness?.manifest || !witness?.integrity)
159
+ throw new Error('not a proofseal witness document');
160
+ }
161
+ catch (e) {
162
+ return precondition('manifest-unparseable', `could not parse ${manifestPath}: ${e.message}`);
163
+ }
164
+ const signature = checkSignature(witness);
165
+ // Platform honesty (premortem #3): warn — never fail — when the verifying
166
+ // OS differs from the (sealed) sealing OS. Manifests sealed before the
167
+ // platform field existed are tolerated silently.
168
+ const currentPlatform = opts.currentPlatform ?? process.platform;
169
+ const sealedOs = witness.manifest.platform?.os;
170
+ const platformWarning = sealedOs && sealedOs !== currentPlatform
171
+ ? `sealed on ${sealedOs}, verifying on ${currentPlatform} — file-hash mismatches on built/binary artifacts may be platform drift, not tampering`
172
+ : undefined;
173
+ const results = [];
174
+ for (const claim of witness.manifest.claims) {
175
+ if (claim.type === 'harness') {
176
+ if (opts.runHarnesses === false)
177
+ continue;
178
+ results.push(await classifyHarnessClaim(root, claim));
179
+ }
180
+ else {
181
+ results.push(classifyFileClaim(root, claim));
182
+ }
183
+ }
184
+ // Per-claim precondition awareness (premortem #5): a MISSING file claim
185
+ // whose path is a build output (dist/, build/, out/) looks like "you did
186
+ // not build" — but ONLY when the build-output directory itself is absent.
187
+ // If dist/ exists and one sealed file inside it is gone, that is a real
188
+ // MISSING (deleted artifact), not an unbuilt checkout (bench finding
189
+ // 2026-06-12: the directory-blind heuristic misclassified 3/45 deletions).
190
+ for (const r of results) {
191
+ if (r.status === 'missing' && r.file && !r.preconditionSuspect) {
192
+ const m = r.file.match(BUILD_OUTPUT_RE);
193
+ if (m) {
194
+ const buildDir = r.file.slice(0, r.file.indexOf(m[2]) + m[2].length);
195
+ if (!existsSync(join(root, buildDir))) {
196
+ r.preconditionSuspect = true;
197
+ r.detail = r.detail ?? `precondition-suspect: build output ${r.file} is absent — was the project built?`;
198
+ }
199
+ }
200
+ }
201
+ }
202
+ const summary = summarize(results);
203
+ // Named precondition (premortem #5): a harness hash mismatch cannot be
204
+ // classified as drift-vs-regressed without its committed reference vector.
205
+ // The overwhelmingly likely cause is seal outputs that were never
206
+ // committed — surface that by name instead of crying "regressed".
207
+ if (results.some((r) => r.referenceVectorMissing)) {
208
+ return {
209
+ ...precondition('reference-vector-not-found', REFERENCE_VECTOR_HINT, summary, signature, results),
210
+ ...(platformWarning ? { platformWarning } : {}),
211
+ };
212
+ }
213
+ // Exit-2 heuristics (issue #1880, relaxed per premortem round 2):
214
+ // (a) EVERY failing claim is precondition-suspect (missing build output
215
+ // and/or harness command not found) ⇒ environment, not regression;
216
+ // (b) legacy net: every claim missing AND the manifest references a
217
+ // build-output path ⇒ source-only checkout.
218
+ const failing = results.filter((r) => r.status === 'regressed' || r.status === 'missing');
219
+ const allFailingSuspect = failing.length > 0 && failing.every((r) => r.preconditionSuspect);
220
+ const fileClaims = witness.manifest.claims.filter((c) => c.type !== 'harness');
221
+ const allMissing = results.length > 0 && summary.missing === results.length;
222
+ const referencesBuildOutput = fileClaims.some((c) => BUILD_OUTPUT_RE.test(normalizeClaimPath(c.file)));
223
+ if (allFailingSuspect || (allMissing && referencesBuildOutput)) {
224
+ const onlyCommandsMissing = allFailingSuspect && failing.every((r) => r.detail?.includes('harness command not found'));
225
+ const reason = onlyCommandsMissing ? 'harness-command-not-found' : 'dist-not-built';
226
+ const hint = onlyCommandsMissing
227
+ ? 'install the harness command(s) listed in the claim details, then re-run verify'
228
+ : 'run npm ci && npm run build';
229
+ return {
230
+ ...precondition(reason, hint, summary, signature, results),
231
+ ...(platformWarning ? { platformWarning } : {}),
232
+ };
233
+ }
234
+ const sigOk = signature.manifestHashOk && signature.publicKeyReproducible && signature.signatureValid;
235
+ const ok = sigOk && summary.regressed === 0 && summary.missing === 0;
236
+ return {
237
+ ok,
238
+ exitCode: ok ? 0 : 1,
239
+ signature,
240
+ summary,
241
+ results,
242
+ note: THREAT_MODEL_NOTE,
243
+ ...(platformWarning ? { platformWarning } : {}),
244
+ };
245
+ }
246
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/manifest/verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function startMcpServer(): Promise<void>;
@@ -0,0 +1,138 @@
1
+ /**
2
+ * ProofSeal MCP stdio server (ADR-0001 §4.2) — thin wrappers over the
3
+ * library API. Every tool is fail-open: a broken repo returns
4
+ * {ok:false, warn:true, error, hint} instead of killing the agent session.
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
8
+ import { z } from 'zod';
9
+ import { seal } from '../manifest/seal.js';
10
+ import { verify, toVerifyJson, classifyFileClaim } from '../manifest/verify.js';
11
+ import { loadHistory } from '../history/jsonl.js';
12
+ import { fixTimeline, findRegressionIntroductions } from '../history/queries.js';
13
+ import { enrichRegressionsWithGit } from '../history/gitinfo.js';
14
+ import { runHarness } from '../harness/run.js';
15
+ import { loadConfig } from '../config.js';
16
+ import { readFileSync } from 'node:fs';
17
+ /** Contract §6: structuredContent is primary; JSON mirrored into content[0].text. */
18
+ function asText(data) {
19
+ return {
20
+ content: [{ type: 'text', text: JSON.stringify(data, null, 2) }],
21
+ structuredContent: data,
22
+ };
23
+ }
24
+ /** Fail-open wrapper (RuView rvagent convention). */
25
+ async function failOpen(hint, fn) {
26
+ try {
27
+ return asText(await fn());
28
+ }
29
+ catch (e) {
30
+ return asText({ ok: false, warn: true, error: e.message, hint });
31
+ }
32
+ }
33
+ /**
34
+ * Client-disconnect hygiene: when the MCP client goes away mid-write, the
35
+ * stdio transport surfaces `write EPIPE` (and stdin sees EOF). A vanished
36
+ * client is a normal shutdown, not an error — exit 0 quietly. Anything that
37
+ * is NOT an EPIPE still crashes loudly (stack to stderr, exit 1) so real
38
+ * bugs are never swallowed.
39
+ */
40
+ function installStdioShutdownHandlers() {
41
+ const isEpipe = (err) => err?.code === 'EPIPE';
42
+ process.stdout.on('error', (err) => {
43
+ if (isEpipe(err))
44
+ process.exit(0);
45
+ throw err; // escalates to the uncaughtException guard below
46
+ });
47
+ process.stdin.on('error', (err) => {
48
+ if (isEpipe(err) || err.code === 'EOF')
49
+ process.exit(0);
50
+ throw err;
51
+ });
52
+ // stdin EOF = client closed the session: drain queued stdout, then exit 0.
53
+ process.stdin.on('end', () => {
54
+ process.stdout.write('', () => process.exit(0));
55
+ });
56
+ // Narrow guard: ONLY EPIPE exits quietly. Every other uncaught error keeps
57
+ // the default fatal semantics (stack trace on stderr, nonzero exit).
58
+ process.on('uncaughtException', (err) => {
59
+ if (isEpipe(err))
60
+ process.exit(0);
61
+ console.error(err);
62
+ process.exit(1);
63
+ });
64
+ }
65
+ export async function startMcpServer() {
66
+ installStdioShutdownHandlers();
67
+ const server = new McpServer({ name: 'proofseal', version: '0.1.0' });
68
+ server.tool('verify_claims', 'Verify the sealed ProofSeal manifest against the live tree: integrity-seal triple-check plus per-claim pass/drift/regressed/missing classification. Use when raw Bash (sha256sum, grep) is wrong because it cannot detect manifest tampering or distinguish benign drift from a real regression.', { root: z.string().optional(), manifest: z.string().optional() }, async ({ root, manifest }) => failOpen('run `proofseal init` then `proofseal seal` in the repo', async () => {
69
+ const r = await verify({ root, manifestPath: manifest });
70
+ // verify() never throws on broken repos — surface preconditions in the
71
+ // fail-open shape so agent sessions get {ok:false, warn:true, error, hint}.
72
+ if (r.precondition) {
73
+ return { ok: false, warn: true, error: r.precondition, hint: r.hint ?? '', detail: toVerifyJson(r) };
74
+ }
75
+ return toVerifyJson(r);
76
+ }));
77
+ server.tool('seal_manifest', 'Refresh all claims against the tree, derive the commit-bound key, seal the manifest, and append a history snapshot. Use when manually editing proofs/manifest.json is wrong because hand-edited manifests always break the seal — resealing is the only legal mutation.', { root: z.string().optional() }, async ({ root }) => failOpen('ensure the repo has proofseal.json (run `proofseal init`) and is a git checkout', async () => {
78
+ const r = await seal({ root });
79
+ return { ok: r.ok, summary: r.summary, manifestPath: r.manifestPath, manifestHash: r.witness.integrity.manifestHash, warnings: r.warnings, filesWritten: r.filesWritten };
80
+ }));
81
+ server.tool('check_drift', 'Diff the live tree against the latest sealed manifest WITHOUT resealing: reports per-claim pass/drift/regressed/missing only. Use when seal_manifest is wrong because you only want to inspect drift, not mint a new sealed snapshot.', { root: z.string().optional(), manifest: z.string().optional() }, async ({ root, manifest }) => failOpen('seal a manifest first with `proofseal seal`', () => {
82
+ const cfg = loadConfig(root ?? process.cwd());
83
+ const path = manifest ?? cfg.manifestPath;
84
+ const witness = JSON.parse(readFileSync(path, 'utf8'));
85
+ const results = witness.manifest.claims
86
+ .filter((c) => c.type !== 'harness')
87
+ .map((c) => classifyFileClaim(cfg.root, c));
88
+ return {
89
+ ok: true,
90
+ summary: {
91
+ pass: results.filter((r) => r.status === 'pass').length,
92
+ drift: results.filter((r) => r.status === 'drift').length,
93
+ regressed: results.filter((r) => r.status === 'regressed').length,
94
+ missing: results.filter((r) => r.status === 'missing').length,
95
+ },
96
+ results,
97
+ };
98
+ }));
99
+ server.tool('claim_history', 'Status timeline (pass/regressed/absent) for one claim across every sealed snapshot. Use when `git log` is wrong because it shows commits, not whether a specific verified claim held at each seal point.', { id: z.string(), root: z.string().optional() }, async ({ id, root }) => failOpen('no history yet — run `proofseal seal` at least once', () => {
100
+ const cfg = loadConfig(root ?? process.cwd());
101
+ return { ok: true, id, timeline: fixTimeline(loadHistory(cfg.historyPath), id) };
102
+ }));
103
+ server.tool('find_regression', 'Bisect the JSONL history: for every currently-regressed claim, locate the last-pass snapshot and the snapshot where the regression appeared. Use when `git bisect` is wrong because it needs a runnable predicate per commit; this answers from already-recorded seal snapshots instantly.', { root: z.string().optional() }, async ({ root }) => failOpen('no history yet — run `proofseal seal` at least once', () => {
104
+ const cfg = loadConfig(root ?? process.cwd());
105
+ // Same query code as `proofseal history --bisect`: entries are ordered
106
+ // by issuedAt, and each regression carries reachability/range-width
107
+ // info when git can resolve the recorded SHAs (best-effort).
108
+ return {
109
+ ok: true,
110
+ regressions: enrichRegressionsWithGit(cfg.root, findRegressionIntroductions(loadHistory(cfg.historyPath))),
111
+ };
112
+ }));
113
+ server.tool('run_harness', 'Run a deterministic harness (seeded via PROOFSEAL_SEED), quantize numeric output (round-half-even), hash it, and compare against the committed expectation with an rtol/atol tolerance fallback. Use when plain Bash execution is wrong because raw float output hashes diverge across CPU microarchitectures.', { name: z.string(), root: z.string().optional() }, async ({ name, root }) => failOpen('declare the harness claim in proofseal.json and run `proofseal harness run --update` first', async () => {
114
+ const cfg = loadConfig(root ?? process.cwd());
115
+ const def = cfg.config.claims.find((c) => c.type === 'harness' && (c.harness === name || c.id === name));
116
+ if (!def)
117
+ throw new Error(`no harness claim named '${name}'`);
118
+ const result = await runHarness({
119
+ name,
120
+ cmd: def.cmd,
121
+ cwd: cfg.root,
122
+ seed: def.seed,
123
+ quantizeDecimals: def.quantizeDecimals,
124
+ exclude: def.exclude,
125
+ expectedSha256: def.expectedSha256,
126
+ referenceVector: def.referenceVector,
127
+ tolerance: def.tolerance,
128
+ });
129
+ const { values: _v, quantized: _q, ...compact } = result;
130
+ return { ok: result.status === 'pass' || result.status === 'drift', result: compact };
131
+ }));
132
+ server.tool('list_claims', 'List the claims declared in proofseal.json (id, type, target). Use when reading proofseal.json with a file tool is wrong because this validates the schema and resolves defaults.', { root: z.string().optional() }, async ({ root }) => failOpen('run `proofseal init` to create proofseal.json', () => {
133
+ const cfg = loadConfig(root ?? process.cwd());
134
+ return { ok: true, claims: cfg.config.claims };
135
+ }));
136
+ await server.connect(new StdioServerTransport());
137
+ }
138
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAC3C,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,iBAAiB,EAAoB,MAAM,uBAAuB,CAAC;AAClG,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,2BAA2B,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQvC,qFAAqF;AACrF,SAAS,MAAM,CAAC,IAAa;IAC3B,OAAO;QACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QAChE,iBAAiB,EAAE,IAA+B;KACnD,CAAC;AACJ,CAAC;AAED,qDAAqD;AACrD,KAAK,UAAU,QAAQ,CAAC,IAAY,EAAE,EAAoC;IACxE,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAC5B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,MAAM,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAG,CAAW,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9E,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,4BAA4B;IACnC,MAAM,OAAO,GAAG,CAAC,GAAY,EAAW,EAAE,CACvC,GAAyC,EAAE,IAAI,KAAK,OAAO,CAAC;IAE/D,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QACxD,IAAI,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,MAAM,GAAG,CAAC,CAAC,iDAAiD;IAC9D,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE;QACvD,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,KAAK,KAAK;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,GAAG,CAAC;IACZ,CAAC,CAAC,CAAC;IACH,2EAA2E;IAC3E,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;QAC3B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IACH,2EAA2E;IAC3E,qEAAqE;IACrE,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,CAAC,GAAG,EAAE,EAAE;QACtC,IAAI,OAAO,CAAC,GAAG,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,4BAA4B,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAEtE,MAAM,CAAC,IAAI,CACT,eAAe,EACf,kSAAkS,EAClS,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAChE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC3B,QAAQ,CAAC,wDAAwD,EAAE,KAAK,IAAI,EAAE;QAC5E,MAAM,CAAC,GAAG,MAAM,MAAM,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzD,uEAAuE;QACvE,4EAA4E;QAC5E,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC;YACnB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,YAAY,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;QACvG,CAAC;QACD,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,yQAAyQ,EACzQ,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAC/B,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CACjB,QAAQ,CAAC,iFAAiF,EAAE,KAAK,IAAI,EAAE;QACrG,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC;IAC5K,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,uOAAuO,EACvO,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAChE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE,CAC3B,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;QAC3D,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,GAAG,QAAQ,IAAI,GAAG,CAAC,YAAY,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAY,CAAC;QAClE,MAAM,OAAO,GAAkB,OAAO,CAAC,QAAQ,CAAC,MAAM;aACnD,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;aACnC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO;YACL,EAAE,EAAE,IAAI;YACR,OAAO,EAAE;gBACP,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,MAAM;gBACvD,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,MAAM;gBACzD,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,WAAW,CAAC,CAAC,MAAM;gBACjE,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,MAAM;aAC9D;YACD,OAAO;SACR,CAAC;IACJ,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,eAAe,EACf,0MAA0M,EAC1M,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAC/C,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CACrB,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;IACnF,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,iBAAiB,EACjB,4RAA4R,EAC5R,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAC/B,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CACjB,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;QACnE,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,uEAAuE;QACvE,oEAAoE;QACpE,6DAA6D;QAC7D,OAAO;YACL,EAAE,EAAE,IAAI;YACR,WAAW,EAAE,wBAAwB,CACnC,GAAG,CAAC,IAAI,EACR,2BAA2B,CAAC,WAAW,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAC1D;SACF,CAAC;IACJ,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,gTAAgT,EAChT,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EACjD,KAAK,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CACvB,QAAQ,CAAC,4FAA4F,EAAE,KAAK,IAAI,EAAE;QAChH,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAChC,CAAC,CAAC,EAAqB,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CACxF,CAAC;QACF,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,GAAG,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC;YAC9B,IAAI;YACJ,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,GAAG,EAAE,GAAG,CAAC,IAAI;YACb,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;YACtC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,cAAc,EAAE,GAAG,CAAC,cAAc;YAClC,eAAe,EAAE,GAAG,CAAC,eAAe;YACpC,SAAS,EAAE,GAAG,CAAC,SAAS;SACzB,CAAC,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC;QACzD,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;IACxF,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,CAAC,IAAI,CACT,aAAa,EACb,mLAAmL,EACnL,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,EAAE,EAC/B,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CACjB,QAAQ,CAAC,+CAA+C,EAAE,GAAG,EAAE;QAC7D,MAAM,GAAG,GAAG,UAAU,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;QAC9C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;IACjD,CAAC,CAAC,CACL,CAAC;IAEF,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC"}
package/package.json CHANGED
@@ -1,29 +1,59 @@
1
1
  {
2
2
  "name": "proofseal",
3
- "version": "0.0.2",
4
- "description": "Seal your README claims and verify them in CI v0.1.0 in private beta",
3
+ "version": "0.1.0",
4
+ "description": "Witness-chained, tamper-evident claim verification for any git repocommit-bound integrity seals, zero key management.",
5
+ "type": "module",
5
6
  "license": "MIT",
6
7
  "author": "rudycelekli",
7
8
  "repository": {
8
9
  "type": "git",
9
10
  "url": "git+https://github.com/rudycelekli/proofseal.git"
10
11
  },
11
- "homepage": "https://github.com/rudycelekli/proofseal#readme",
12
12
  "bugs": {
13
13
  "url": "https://github.com/rudycelekli/proofseal/issues"
14
14
  },
15
+ "homepage": "https://github.com/rudycelekli/proofseal#readme",
16
+ "engines": {
17
+ "node": ">=20"
18
+ },
19
+ "bin": {
20
+ "proofseal": "dist/cli/index.js"
21
+ },
22
+ "main": "dist/index.js",
23
+ "types": "dist/index.d.ts",
24
+ "exports": {
25
+ ".": {
26
+ "types": "./dist/index.d.ts",
27
+ "import": "./dist/index.js"
28
+ }
29
+ },
30
+ "files": [
31
+ "dist",
32
+ "NOTICE",
33
+ "LICENSE"
34
+ ],
35
+ "scripts": {
36
+ "build": "tsc",
37
+ "pretest": "npm run build",
38
+ "test": "node --test \"tests/unit/**/*.test.mjs\"",
39
+ "test:integration": "node --test \"tests/integration/**/*.test.{mjs,js}\"",
40
+ "smoke:tarball": "node scripts/tarball-smoke.mjs"
41
+ },
15
42
  "keywords": [
16
- "readme",
17
43
  "verification",
18
- "drift",
19
- "ci",
20
- "claims"
44
+ "tamper-evidence",
45
+ "integrity-seal",
46
+ "witness",
47
+ "claims",
48
+ "provenance"
21
49
  ],
22
- "bin": {
23
- "proofseal": "./bin.js"
50
+ "dependencies": {
51
+ "@modelcontextprotocol/sdk": "^1.12.1",
52
+ "commander": "^12.1.0",
53
+ "zod": "^3.23.8"
24
54
  },
25
- "files": [
26
- "bin.js",
27
- "README.md"
28
- ]
55
+ "devDependencies": {
56
+ "@types/node": "^20.14.0",
57
+ "typescript": "^5.5.0"
58
+ }
29
59
  }
package/bin.js DELETED
@@ -1,19 +0,0 @@
1
- #!/usr/bin/env node
2
- "use strict";
3
-
4
- const lines = [
5
- "",
6
- " ProofSeal",
7
- " ---------",
8
- " Seals the claims in your README (file hashes, markers, test harnesses)",
9
- " and verifies them in CI: pass / drift / regressed / missing.",
10
- "",
11
- " Status: v0.1.0 is in private beta. This package is a placeholder.",
12
- "",
13
- " Watch or star https://github.com/rudycelekli/proofseal and subscribe",
14
- " to the \"Notify me\" issue there to hear about the release.",
15
- "",
16
- ];
17
-
18
- process.stdout.write(lines.join("\n") + "\n");
19
- process.exit(0);