mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-10-23 03:47:00 +09:00
Extends verification.md.json from 27 fix-witnesses to 55 by adding 28
capability-witnesses — one per source file under
v3/@claude-flow/cli/src/mcp-tools/. Each new entry hashes the
compiled dist .js and pins a marker tool name that must remain
defined for the witness to verify.
scripts/sign-witness-from-inventory.mjs (new):
Reads verification-inventory.json, groups MCP tools by source file,
maps each src/mcp-tools/foo.ts → dist/src/mcp-tools/foo.js, and
appends a `CAP-MCP-foo` fix entry. Idempotent — re-running replaces
any pre-existing CAP-MCP-* entries instead of duplicating.
Pipeline:
1. node scripts/inventory-capabilities.mjs --json > verification-inventory.json
2. npm run build (in v3/@claude-flow/cli)
3. node scripts/sign-witness-from-inventory.mjs # plant CAP-MCP-* entries
4. node scripts/regenerate-witness.mjs # re-hash + re-sign
Result for 3.6.25:
preserved fix entries: 27 (F1..F12, G1..G7, #1697/#1698/#1691/#1721, ADR-094)
CAP-MCP entries added: 28 (300 tools across 28 source files)
total fixes: 55
verified: 55 / 55 (all green)
End-to-end smoke test of the published 3.6.25 (npx -y ruflo@3.6.25):
- MCP server initializes cleanly in stdio mode
- tools/list returns 239 tool definitions
- All major categories present: agent_*, memory_*, hooks_*, github_*,
aidefence_*, federation_*, workflow_*, swarm_*, browser_*, terminal_*,
ruvllm_*
Bridge integration validated locally (ruflo/src/mcp-bridge):
- npm install in bridge dir → 69 packages clean
- bridge spawns `npx -y ruflo mcp start` → 238 ruflo tools loaded
- HTTP /mcp endpoint round-trips initialize, tools/list, tools/call
- Real tool invocation: tools/call ruflo__agent_list returns
{agents: [], total: 0, filters: {}} — expected empty-state shape
- /health reports 3 builtin + 51 external = 54 total exposed
- Clean shutdown on SIGTERM
Task #26 (functional smoke tests for `ruflo verify --functional`)
remains the next iteration: bake this manual smoke into a verify
subcommand that round-trips each MCP tool through the in-process
server.
GCP Cloud Run rebuild (which would pull 3.6.25 via `npm install -g
ruflo`) is out of scope here — no cloudbuild.yaml in the bridge dir
and config/config.json is a per-deployment secret. Local validation
above proves the publish is consumable; container rebuild on the
deployment side picks it up automatically.
This commit is contained in:
1 parent
f8cd1c9fe2
commit
9d43d8fdb4
2 files changed
+344
-7
No files matched your search
@@ -0,0 +1,113 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Extend verification.md.json with per-source-file witnesses for every
|
||||
* MCP tool group in verification-inventory.json (task #25).
|
||||
*
|
||||
* Today the manifest carries 27 *fix* witnesses (regression-flavored).
|
||||
* This script adds *capability* witnesses — one entry per source file
|
||||
* that defines MCP tools — so `ruflo verify` can confirm the entire
|
||||
* 300-tool surface byte-for-byte against its dist counterpart.
|
||||
*
|
||||
* ID convention: `CAP-MCP-<src-basename-without-ext>`. Stable across
|
||||
* regens so runs are idempotent.
|
||||
*
|
||||
* Marker: the first tool name (alphabetical) defined in that source
|
||||
* file. If `ruflo verify` finds the marker missing in the cited dist
|
||||
* file, that tool was renamed/removed — a real regression signal.
|
||||
*
|
||||
* Run order:
|
||||
* 1. node scripts/inventory-capabilities.mjs --json > verification-inventory.json
|
||||
* 2. npm run build (in v3/@claude-flow/cli)
|
||||
* 3. node scripts/sign-witness-from-inventory.mjs
|
||||
* 4. node scripts/regenerate-witness.mjs (re-hashes + re-signs)
|
||||
*
|
||||
* Step 3 only mutates `fixes[]` — step 4 picks up the changes and
|
||||
* re-derives all hashes + signatures.
|
||||
*/
|
||||
|
||||
import { readFileSync, writeFileSync, existsSync } from 'node:fs';
|
||||
import { dirname, join, basename } from 'node:path';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
const ROOT = (() => {
|
||||
let dir = fileURLToPath(new URL('.', import.meta.url));
|
||||
while (dir !== '/') {
|
||||
if (existsSync(join(dir, 'verification.md'))) return dir;
|
||||
dir = dirname(dir);
|
||||
}
|
||||
throw new Error('project root not found');
|
||||
})();
|
||||
|
||||
const INVENTORY = JSON.parse(readFileSync(join(ROOT, 'verification-inventory.json'), 'utf-8'));
|
||||
const WITNESS_PATH = join(ROOT, 'verification.md.json');
|
||||
const witness = JSON.parse(readFileSync(WITNESS_PATH, 'utf-8'));
|
||||
const m = witness.manifest;
|
||||
|
||||
// Map src/mcp-tools/foo.ts → dist/src/mcp-tools/foo.js
|
||||
function srcToDist(srcPath) {
|
||||
return srcPath
|
||||
.replace('/src/', '/dist/src/')
|
||||
.replace(/\.ts$/, '.js');
|
||||
}
|
||||
|
||||
// Group MCP tools by source file (sorted by file path; tools sorted alpha)
|
||||
const byFile = new Map();
|
||||
for (const tool of INVENTORY.mcp) {
|
||||
if (!byFile.has(tool.sourceFile)) byFile.set(tool.sourceFile, []);
|
||||
byFile.get(tool.sourceFile).push(tool.name);
|
||||
}
|
||||
for (const list of byFile.values()) list.sort();
|
||||
|
||||
// Build candidate fix entries
|
||||
const candidates = [];
|
||||
let skipped = 0;
|
||||
for (const [srcFile, tools] of [...byFile.entries()].sort()) {
|
||||
const distFile = srcToDist(srcFile);
|
||||
const distAbs = join(ROOT, distFile);
|
||||
if (!existsSync(distAbs)) {
|
||||
console.warn(`[skip] no dist for ${srcFile} (looked at ${distFile})`);
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
const baseName = basename(srcFile, '.ts');
|
||||
const id = `CAP-MCP-${baseName}`;
|
||||
// Marker: first tool name alphabetically. The dist must literally contain
|
||||
// this string for the witness to verify — protects against the file
|
||||
// existing but no longer defining the tool.
|
||||
const marker = tools[0];
|
||||
const desc = tools.length === 1
|
||||
? `MCP tool: ${tools[0]}`
|
||||
: `MCP tools (${tools.length}): ${tools.slice(0, 3).join(', ')}${tools.length > 3 ? ', …' : ''}`;
|
||||
candidates.push({
|
||||
id,
|
||||
desc,
|
||||
file: distFile,
|
||||
// sha256 + markerVerified are computed by regenerate-witness.mjs
|
||||
// when it walks the manifest; we just plant placeholders here.
|
||||
sha256: '',
|
||||
marker,
|
||||
markerVerified: false,
|
||||
_capabilityCount: tools.length,
|
||||
});
|
||||
}
|
||||
|
||||
// Merge: keep existing fixes that aren't in the CAP-MCP namespace.
|
||||
// Replace any pre-existing CAP-MCP-* entries so re-runs are idempotent.
|
||||
const preserved = m.fixes.filter(f => !f.id.startsWith('CAP-MCP-'));
|
||||
const merged = [...preserved, ...candidates.map(({ _capabilityCount: _, ...c }) => c)];
|
||||
m.fixes = merged;
|
||||
m.summary = {
|
||||
totalFixes: merged.length,
|
||||
verified: 0, // regenerate-witness.mjs recomputes
|
||||
failed: 0,
|
||||
};
|
||||
|
||||
writeFileSync(WITNESS_PATH, JSON.stringify(witness, null, 2) + '\n', 'utf-8');
|
||||
|
||||
console.log(`Inventory-driven witnesses planted in ${WITNESS_PATH}`);
|
||||
console.log(` preserved fix entries: ${preserved.length}`);
|
||||
console.log(` CAP-MCP entries added: ${candidates.length} (${INVENTORY.mcp.length} tools across ${byFile.size} source files)`);
|
||||
console.log(` skipped (no dist): ${skipped}`);
|
||||
console.log(` total fixes now: ${merged.length}`);
|
||||
console.log();
|
||||
console.log(`Next: run \`node scripts/regenerate-witness.mjs\` to hash + sign.`);
|
||||
+231
-7
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"manifest": {
|
||||
"schema": "ruflo-witness/v1",
|
||||
"issuedAt": "2026-05-04T01:39:34.896Z",
|
||||
"gitCommit": "8c0d580111e447aeed6f9971465180063ce1a9d3",
|
||||
"issuedAt": "2026-05-04T01:44:08.951Z",
|
||||
"gitCommit": "f8cd1c9fe24d0b86e51338f3a31d4ae49f5d1f38",
|
||||
"branch": "fix/issues-may-1-3",
|
||||
"releases": {
|
||||
"ruflo": "3.6.25",
|
||||
"@claude-flow/cli": "3.6.25"
|
||||
},
|
||||
"summary": {
|
||||
"totalFixes": 27,
|
||||
"verified": 27,
|
||||
"totalFixes": 55,
|
||||
"verified": 55,
|
||||
"failed": 0
|
||||
},
|
||||
"fixes": [
|
||||
@@ -229,15 +229,239 @@
|
||||
"sha256": "881dad4fa9dc19a539c1a46dfe27c77984596cdd05759937909aacf028378acc",
|
||||
"marker": "@noble/ed25519",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-agent-tools",
|
||||
"desc": "MCP tools (8): agent_execute, agent_health, agent_list, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/agent-tools.js",
|
||||
"sha256": "95442f5e700427caf9b360c71317b446f584fc67e21698c9f9ca815d869c13df",
|
||||
"marker": "agent_execute",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-agentdb-tools",
|
||||
"desc": "MCP tools (15): agentdb_batch, agentdb_causal-edge, agentdb_consolidate, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/agentdb-tools.js",
|
||||
"sha256": "68d7257df63e72a441c444df7f5ed697117d31802c220a2234ff9e6d678d57ac",
|
||||
"marker": "agentdb_batch",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-analyze-tools",
|
||||
"desc": "MCP tools (6): analyze_diff, analyze_diff-classify, analyze_diff-reviewers, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/analyze-tools.js",
|
||||
"sha256": "34c78f417c395ca9df13e53c35c4d47153818f9d10a019e3e299da150c7329c4",
|
||||
"marker": "analyze_diff",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-autopilot-tools",
|
||||
"desc": "MCP tools (10): autopilot_config, autopilot_disable, autopilot_enable, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/autopilot-tools.js",
|
||||
"sha256": "927df07df0cbe27e8ce0a77ec99529beb62e222649854ef2d1e6d21ad2f446c9",
|
||||
"marker": "autopilot_config",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-browser-tools",
|
||||
"desc": "MCP tools (23): browser_back, browser_check, browser_click, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/browser-tools.js",
|
||||
"sha256": "2c075877030bba617709030487675296a9bfddcfc15ea4c30beedbd7d83cf94a",
|
||||
"marker": "browser_back",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-claims-tools",
|
||||
"desc": "MCP tools (12): claims_accept-handoff, claims_board, claims_claim, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/claims-tools.js",
|
||||
"sha256": "2a00b654e87dd75b9cbb36a0d32e41443c275f5bdf939136c6a397c355f83aa7",
|
||||
"marker": "claims_accept-handoff",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-config-tools",
|
||||
"desc": "MCP tools (6): config_export, config_get, config_import, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/config-tools.js",
|
||||
"sha256": "811ac1297fea330f0e497523a234eb97339a4e1c009b2c33be14915b662b7dec",
|
||||
"marker": "config_export",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-coordination-tools",
|
||||
"desc": "MCP tools (7): coordination_consensus, coordination_load_balance, coordination_metrics, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/coordination-tools.js",
|
||||
"sha256": "5d9b47750015c4626b044453494ef9905ccda9cbb35a06f56215783b6251cef0",
|
||||
"marker": "coordination_consensus",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-daa-tools",
|
||||
"desc": "MCP tools (8): daa_agent_adapt, daa_agent_create, daa_cognitive_pattern, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/daa-tools.js",
|
||||
"sha256": "90828f0744e1769212a079ef01c13c4a7d2f0d77d6036978a18b94134beef14a",
|
||||
"marker": "daa_agent_adapt",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-embeddings-tools",
|
||||
"desc": "MCP tools (10): embeddings_compare, embeddings_generate, embeddings_hyperbolic, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/embeddings-tools.js",
|
||||
"sha256": "6f0f172840b7db1a491356bed5f7b6b6f6e8760633cd38e1bc968f4aa22bc946",
|
||||
"marker": "embeddings_compare",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-github-tools",
|
||||
"desc": "MCP tools (5): github_issue_track, github_metrics, github_pr_manage, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/github-tools.js",
|
||||
"sha256": "5987990581843350f1e01490648dd7b85d8e02bbbce8d9551438219e23bef5ec",
|
||||
"marker": "github_issue_track",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-guidance-tools",
|
||||
"desc": "MCP tools (5): guidance_capabilities, guidance_discover, guidance_quickref, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/guidance-tools.js",
|
||||
"sha256": "c6e4b76e3ea97b9689a8ab7c72f286e653c46e95b59f1f49fe3615f960c1214e",
|
||||
"marker": "guidance_capabilities",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-hive-mind-tools",
|
||||
"desc": "MCP tools (9): hive-mind_broadcast, hive-mind_consensus, hive-mind_init, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/hive-mind-tools.js",
|
||||
"sha256": "6987df2e11f6c5fe7cb2a4f5b2ba8c883a6705b447b3c0d0f237a2187e5e28a4",
|
||||
"marker": "hive-mind_broadcast",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-hooks-tools",
|
||||
"desc": "MCP tools (62): build-agents, explain, hooks_build-agents, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js",
|
||||
"sha256": "11a78ae628c5e1fa6a998294e3a0398bcaf40291a5aca103a3596e556aeabfc5",
|
||||
"marker": "build-agents",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-memory-tools",
|
||||
"desc": "MCP tools (10): memory_bridge_status, memory_delete, memory_import_claude, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/memory-tools.js",
|
||||
"sha256": "dfa12dd4c22dc0908e0ff7b351fc1c371f49ca70a28392aaf9fc732c9ce5f224",
|
||||
"marker": "memory_bridge_status",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-neural-tools",
|
||||
"desc": "MCP tools (6): neural_compress, neural_optimize, neural_patterns, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.js",
|
||||
"sha256": "4d750ebae6f7ab427b2ae2b37949fa123aee5f5c5718d550eb8c702360da4f8c",
|
||||
"marker": "neural_compress",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-performance-tools",
|
||||
"desc": "MCP tools (6): performance_benchmark, performance_bottleneck, performance_metrics, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/performance-tools.js",
|
||||
"sha256": "d612f3c006c7c1bf3283c0c257bc24557feff65f8b1f3dbb32c4b9a33478767c",
|
||||
"marker": "performance_benchmark",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-progress-tools",
|
||||
"desc": "MCP tools (4): progress_check, progress_summary, progress_sync, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/progress-tools.js",
|
||||
"sha256": "6b9c5c1b27687cfaa1f6b47b245a8b25d98d16418221b0a462f1a11b5b090710",
|
||||
"marker": "progress_check",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-ruvllm-tools",
|
||||
"desc": "MCP tools (10): ruvllm_chat_format, ruvllm_generate_config, ruvllm_hnsw_add, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/ruvllm-tools.js",
|
||||
"sha256": "31eb7e4ee42c506685a85008740e83aee2b1d12df6189d4f9bf3f450e0223b37",
|
||||
"marker": "ruvllm_chat_format",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-security-tools",
|
||||
"desc": "MCP tools (6): aidefence_analyze, aidefence_has_pii, aidefence_is_safe, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/security-tools.js",
|
||||
"sha256": "bc0c3fee9affe57736b9348fce4520cc437d50cba854ea8a095808d6dbccddbd",
|
||||
"marker": "aidefence_analyze",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-session-tools",
|
||||
"desc": "MCP tools (5): session_delete, session_info, session_list, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/session-tools.js",
|
||||
"sha256": "f623493c80bd305bbf9bf426563db5a9ad745817972bc5690c84a1d1b33e92b9",
|
||||
"marker": "session_delete",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-swarm-tools",
|
||||
"desc": "MCP tools (9): agents, coordinator, persistence, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/swarm-tools.js",
|
||||
"sha256": "50593c3e676044328da0d4f3ff225c0dcfac88b62dfb17210396200a942d4f43",
|
||||
"marker": "agents",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-system-tools",
|
||||
"desc": "MCP tools (15): config, database, disk, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.js",
|
||||
"sha256": "1f50f3378e0ffa77a70e1ad55ee3f8ac3144314715105d3ee8bb824b1d02643b",
|
||||
"marker": "config",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-task-tools",
|
||||
"desc": "MCP tools (7): task_assign, task_cancel, task_complete, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/task-tools.js",
|
||||
"sha256": "da3443945cfe91c4f253ead1b26c7c7995c1e89c0a6de3afa063b282de4416c8",
|
||||
"marker": "task_assign",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-terminal-tools",
|
||||
"desc": "MCP tools (5): terminal_close, terminal_create, terminal_execute, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/terminal-tools.js",
|
||||
"sha256": "ee54c3dc39f88da154722e1955ed88814e54e653f3b30848e4217eedf2352183",
|
||||
"marker": "terminal_close",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-transfer-tools",
|
||||
"desc": "MCP tools (11): transfer_detect-pii, transfer_ipfs-resolve, transfer_plugin-featured, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/transfer-tools.js",
|
||||
"sha256": "a58b95f7e702f72d1f142511bdf530116586138b90aca0e2833b8817799ed27f",
|
||||
"marker": "transfer_detect-pii",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-wasm-agent-tools",
|
||||
"desc": "MCP tools (10): wasm_agent_create, wasm_agent_export, wasm_agent_files, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/wasm-agent-tools.js",
|
||||
"sha256": "1240f6d8df2de25f909040c5b522bbf7fadc5427df74e377fa56f4b8fd61ce5f",
|
||||
"marker": "wasm_agent_create",
|
||||
"markerVerified": true
|
||||
},
|
||||
{
|
||||
"id": "CAP-MCP-workflow-tools",
|
||||
"desc": "MCP tools (10): workflow_cancel, workflow_create, workflow_delete, …",
|
||||
"file": "v3/@claude-flow/cli/dist/src/mcp-tools/workflow-tools.js",
|
||||
"sha256": "b562d739deb768e58bfd21d79cf30c7898a0c9a3d944d8fabebd218b4c4c305e",
|
||||
"marker": "workflow_cancel",
|
||||
"markerVerified": true
|
||||
}
|
||||
]
|
||||
},
|
||||
"integrity": {
|
||||
"manifestHashAlgo": "sha256",
|
||||
"manifestHash": "94738a0771a21853f93db19bd98a4defa2c4d184f3e7c4d7fa2a10deb111781b",
|
||||
"manifestHash": "eadefd53664bacbd770462576bfa7c8b8467c7651c139b5962923be07918b2d6",
|
||||
"signatureAlgo": "ed25519",
|
||||
"publicKey": "8fb4d6709cdac42cda55a96ad0b16f38f0481b3de1bb7c2529821b0703d663a2",
|
||||
"signature": "8ed98caa63acabbd2565e8ee495360229377a25e627e180abc4ddf4afed85d090060a6af6fa448b0e2f0cd676d4e01c0b1c8e297c9ba12da52c097a684c55305",
|
||||
"publicKey": "be2312d5493c3a66600a3267d2505ab4f55e3d914e5c06f7dfdd24fee12d9539",
|
||||
"signature": "fd72ddd9a596978397c2e494cac6c304297d67e74b33e375b588b65b9e245e8af87665ed25c733c41027092a0040e34c62c085c4a9cd2b78c6fdb781e5d65e06",
|
||||
"seedDerivation": "sha256(gitCommit + ':ruflo-witness/v1')"
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user