From c408364cbe81ab3a76e06f61cea198e83ee5d21e Mon Sep 17 00:00:00 2001 From: Pavel Tkachyk Date: Mon, 17 Aug 2026 16:39:43 -0400 Subject: [PATCH 1/2] Publish v2.0.3 installation instructions Signed-off-by: Pavel Tkachyk --- README.md | 22 +++++++++++----------- SECURITY.md | 2 +- docs/extraction-manifest.json | 10 +++++----- docs/source-of-truth.md | 2 +- scripts/verify_public_plugin_candidate.py | 14 +++++++++++++- tests/test_packaging.py | 4 ++-- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 688a71f..180c038 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Install the official Substrate plugin for my existing Hermes installation by fol "Install with an agent" section of this README exactly. Security and consent rules: -- Install only immutable release v2.0.2 from Substrate-memory/hermes-substrate-wiki. +- Install only immutable release v2.0.3 from Substrate-memory/hermes-substrate-wiki. - Before executing downloaded code, independently verify the installer and plugin archive against the exact SHA-256 values in the README. Never substitute a branch archive, CI artifact, newer release, or checksum obtained only from the same download response. @@ -69,7 +69,7 @@ install_dir="$(mktemp -d)" chmod 700 "$install_dir" cd "$install_dir" -base='https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.2' +base='https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.3' curl --fail --location --proto '=https' --tlsv1.2 --remote-name "$base/install_hermes_plugin.py" curl --fail --location --proto '=https' --tlsv1.2 --remote-name "$base/substrate_wiki.zip" curl --fail --location --proto '=https' --tlsv1.2 --remote-name "$base/SHA256SUMS" @@ -79,8 +79,8 @@ import hashlib from pathlib import Path expected = { - "install_hermes_plugin.py": "4b34ee40d0d08ef24d03128e1cfc5ef73c69b39ca77b3fff59f4a4133cef76f2", - "substrate_wiki.zip": "6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296", + "install_hermes_plugin.py": "72247d3537140098365350020cce29658c0743fee1aa738d7143db82316acce4", + "substrate_wiki.zip": "dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3", } for name, digest in expected.items(): actual = hashlib.sha256(Path(name).read_bytes()).hexdigest() @@ -95,7 +95,7 @@ PY python3 install_hermes_plugin.py \ --archive substrate_wiki.zip \ - --sha256 6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296 \ + --sha256 dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3 \ --yes --json ``` @@ -115,17 +115,17 @@ $installDir = Join-Path ([IO.Path]::GetTempPath()) ("substrate-wiki-" + [guid]:: New-Item -ItemType Directory -Path $installDir | Out-Null Set-Location $installDir -$base = 'https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.2' +$base = 'https://github.com/Substrate-memory/hermes-substrate-wiki/releases/download/v2.0.3' Invoke-WebRequest "$base/install_hermes_plugin.py" -OutFile 'install_hermes_plugin.py' Invoke-WebRequest "$base/substrate_wiki.zip" -OutFile 'substrate_wiki.zip' Invoke-WebRequest "$base/SHA256SUMS" -OutFile 'SHA256SUMS' $installerSha = (Get-FileHash -Algorithm SHA256 'install_hermes_plugin.py').Hash.ToLowerInvariant() $archiveSha = (Get-FileHash -Algorithm SHA256 'substrate_wiki.zip').Hash.ToLowerInvariant() -if ($installerSha -ne '4b34ee40d0d08ef24d03128e1cfc5ef73c69b39ca77b3fff59f4a4133cef76f2') { +if ($installerSha -ne '72247d3537140098365350020cce29658c0743fee1aa738d7143db82316acce4') { throw 'Installer checksum mismatch' } -if ($archiveSha -ne '6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296') { +if ($archiveSha -ne 'dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3') { throw 'Plugin archive checksum mismatch' } $published = Get-Content 'SHA256SUMS' -Raw @@ -136,7 +136,7 @@ if (($published -notmatch [regex]::Escape($installerSha)) -or py -3 install_hermes_plugin.py ` --archive substrate_wiki.zip ` - --sha256 6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296 ` + --sha256 dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3 ` --yes --json ``` @@ -166,7 +166,7 @@ Then verify the content-free state: hermes substrate_wiki onboarding-status --json ``` -Tenant credentials are stored in native credential custody, with an owner-private profile fallback; they never belong in ordinary configuration, logs, arguments, or diagnostics. See [configuration and operation](docs/operation.md) and the immutable [v2.0.2 release](https://github.com/Substrate-memory/hermes-substrate-wiki/releases/tag/v2.0.2). +Tenant credentials are stored in native credential custody, with an owner-private profile fallback; they never belong in ordinary configuration, logs, arguments, or diagnostics. See [configuration and operation](docs/operation.md) and the immutable [v2.0.3 release](https://github.com/Substrate-memory/hermes-substrate-wiki/releases/tag/v2.0.3). ## What it does @@ -189,7 +189,7 @@ Read [SECURITY.md](SECURITY.md), [the threat model](docs/threat-model.md), [the ## Open and paid boundary -The open side is permissively licensed and includes the Hermes plugin/client, memory extraction and entity model, credential containment, privacy deletion, and policy compiler. This Hermes integration itself is hosted-only. [BOUNDARY.md](BOUNDARY.md) distinguishes the permanent commitment from the current `v2.0.2` implementation. +The open side is permissively licensed and includes the Hermes plugin/client, memory extraction and entity model, credential containment, privacy deletion, and policy compiler. This Hermes integration itself is hosted-only. [BOUNDARY.md](BOUNDARY.md) distinguishes the permanent commitment from the current `v2.0.3` implementation. The paid hosted tier covers hosted brokerage, multi-user operation, cross-organizational graph services, audit/attestation, and insurance-backed decisions. Its meter is per authorized action, never seats. This repository does not contain or license those held services. diff --git a/SECURITY.md b/SECURITY.md index 5cd5a63..39f3289 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,7 +2,7 @@ ## Supported versions -The standalone `v2.0.0`, `v2.0.1`, and `v2.0.2` releases and pending `v2.0.3` patch target Hermes 0.20.x and the hosted service at `https://app.trysubstrate.co`. +The standalone `v2.0.0`, `v2.0.1`, `v2.0.2`, and `v2.0.3` releases target Hermes 0.20.x and the hosted service at `https://app.trysubstrate.co`. Candidate CI artifacts are not supported releases. ## Report a vulnerability diff --git a/docs/extraction-manifest.json b/docs/extraction-manifest.json index 414a3f0..5a0b21a 100644 --- a/docs/extraction-manifest.json +++ b/docs/extraction-manifest.json @@ -77,13 +77,13 @@ "class": "standalone_repository_policy_or_test", "path": "README.md", "reason": "Required only by the independent public repository.", - "sha256": "0d74ffbf410fe559478ee6a67e105f275d72d0477c71e86c81531798bc07e599" + "sha256": "20ac49480369c8531e001466a6537a7dae310bbba7e6079bc217a6181e7d69d7" }, { "class": "standalone_repository_policy_or_test", "path": "SECURITY.md", "reason": "Required only by the independent public repository.", - "sha256": "756264bc4dbd9f9df5c6e4bc016545fc1ac0921b384346e40d557706c2137fc5" + "sha256": "d07d0c65e39f0949f91f7a880a4b584b9b57d8ed3c70ca8fd95276d8d525b517" }, { "class": "standalone_repository_policy_or_test", @@ -107,7 +107,7 @@ "class": "standalone_repository_policy_or_test", "path": "docs/source-of-truth.md", "reason": "Required only by the independent public repository.", - "sha256": "3dd139a926518820a81b2ad239ce75028eee6517b717e41386fa1ecb51d02f29" + "sha256": "73d848fd11aff7667f8bdc332ec1b1a872de9998039de0809cf07bd67c7a26e0" }, { "class": "standalone_repository_policy_or_test", @@ -353,7 +353,7 @@ { "class": "build-and-install", "destination": "scripts/verify_public_plugin_candidate.py", - "destination_sha256": "7e0214bb8555fee72327a39f9874707b4eff75aec826916ac604cb904bddd144", + "destination_sha256": "19f9c6d8770943a5e56bef01885f4d29850e26d89dcc8a7695a8c4190f05a641", "source": "scripts/verify_public_plugin_candidate.py", "source_sha256": "4130935d530075fce1758e2e89bd5d973a722e2293b5b1058cfe0d17f326172b", "transformation": "modified_for_standalone" @@ -537,7 +537,7 @@ { "class": "plugin-tests", "destination": "tests/test_packaging.py", - "destination_sha256": "c4033e38f9e832779062381b0d0dcf71eecc25554d8df9af383a2d0c334dcd78", + "destination_sha256": "a3a24a5c987c939514866e72b70d01a32e34f5771089153e1fd12013829d8baf", "source": "tests/contract/test_hermes_plugin_packaging.py", "source_sha256": "c54967830788555b8d7bd5d2f871baeb6b98d7804a2bc7410ab297078bc20ee7", "transformation": "modified_for_standalone" diff --git a/docs/source-of-truth.md b/docs/source-of-truth.md index 2a87fa1..21dab91 100644 --- a/docs/source-of-truth.md +++ b/docs/source-of-truth.md @@ -2,7 +2,7 @@ ## Decision -`Substrate-memory/hermes-substrate-wiki` is the sole editable source for the Hermes `substrate_wiki` plugin. The protected default branch and immutable releases `v1.5.0`, `v2.0.0`, `v2.0.1`, and `v2.0.2` have been read back successfully. +`Substrate-memory/hermes-substrate-wiki` is the sole editable source for the Hermes `substrate_wiki` plugin. The protected default branch and immutable releases `v1.5.0`, `v2.0.0`, `v2.0.1`, and `v2.0.3` have been read back successfully. Substrate-v2 owns only the server and pinned public release references; it must not vendor or modify plugin source. diff --git a/scripts/verify_public_plugin_candidate.py b/scripts/verify_public_plugin_candidate.py index a829292..89732f2 100644 --- a/scripts/verify_public_plugin_candidate.py +++ b/scripts/verify_public_plugin_candidate.py @@ -106,6 +106,7 @@ ), "tests/test_packaging.py": frozenset( { + "a3a24a5c987c939514866e72b70d01a32e34f5771089153e1fd12013829d8baf", "c4033e38f9e832779062381b0d0dcf71eecc25554d8df9af383a2d0c334dcd78", "c7a8e84d116319e62b0b7817c1a049225088c8b3baf59c42ad82cbefc3c172b5", } @@ -133,6 +134,7 @@ "85320ec1e6a8c655b1f4e278b95c1087a6382bf3141366f1290c0933590f4645", "99aed8e5a9a712f0fd2d9caa5223f0b332220f98699351565a3bb35a23d2848c", "bb4ba0542582cf3a89a37906651074c52bd1c28754b079bd67fd856c7fe24362", + "d07d0c65e39f0949f91f7a880a4b584b9b57d8ed3c70ca8fd95276d8d525b517", "ef0cdf7a6c2fdc4ec7e781be15122f9b20331769929517a0f3c82ab15363480b", } ), @@ -209,7 +211,16 @@ # Hosted-origin and legacy-name references are accepted only at these exact reviewed # file digests. Any byte change re-enables all endpoint and credential-name detectors. _HOSTED_ONBOARDING_EXACT_ALLOWLIST = { - 'README.md': frozenset({'87734abc087a4267e77aaeae7fb349d4c19f56dea2f7f3d173ab833dfb1da5e9', '6361beb1a5153f5dbcfca70740c1905096f3bc32ddfd4cc22157c6576c61b83a', 'f139b1328c7884dfa664aa59b47d5d707b2a72894747911b8f99d5e89f6c7eca', 'cdc48a8f8dbe1d68dfe329d5106c55895c5345924544c2cc4b3d7190c837705b', '0d74ffbf410fe559478ee6a67e105f275d72d0477c71e86c81531798bc07e599'}), + 'README.md': frozenset( + { + "0d74ffbf410fe559478ee6a67e105f275d72d0477c71e86c81531798bc07e599", + "20ac49480369c8531e001466a6537a7dae310bbba7e6079bc217a6181e7d69d7", + "6361beb1a5153f5dbcfca70740c1905096f3bc32ddfd4cc22157c6576c61b83a", + "87734abc087a4267e77aaeae7fb349d4c19f56dea2f7f3d173ab833dfb1da5e9", + "cdc48a8f8dbe1d68dfe329d5106c55895c5345924544c2cc4b3d7190c837705b", + "f139b1328c7884dfa664aa59b47d5d707b2a72894747911b8f99d5e89f6c7eca", + } + ), 'COMPATIBILITY.md': frozenset( { "1f18a49d552f2912872c10b0e41e93ff50ccd923d2fa9c108d35084dc5a5b22c", @@ -225,6 +236,7 @@ "85320ec1e6a8c655b1f4e278b95c1087a6382bf3141366f1290c0933590f4645", "99aed8e5a9a712f0fd2d9caa5223f0b332220f98699351565a3bb35a23d2848c", "9cf9406266336996c57227413514cf97a04eb13264d80fa58c54d325fecf3d9f", + "d07d0c65e39f0949f91f7a880a4b584b9b57d8ed3c70ca8fd95276d8d525b517", "ef0cdf7a6c2fdc4ec7e781be15122f9b20331769929517a0f3c82ab15363480b", } ), diff --git a/tests/test_packaging.py b/tests/test_packaging.py index c8e531d..5f7c2ad 100644 --- a/tests/test_packaging.py +++ b/tests/test_packaging.py @@ -91,8 +91,8 @@ def test_root_readme_keeps_published_release_state_truthful() -> None: assert boundary["legal"]["status"] == "published" assert "canonical editable source" in readme assert "`v2.0.3` is not published yet" not in readme - assert "releases/download/v2.0.2" in readme - assert "6140d4f9baa9601e4adc9f75ef96eaf75e031a40767d76795fb08c412344a296" in readme + assert "releases/download/v2.0.3" in readme + assert "dfaa786f68dd819e1313191bb26253caf6bc52fe4b0ab4f6f8c2e2ebcb62e1a3" in readme def test_release_workflow_keeps_dependency_execution_out_of_privileged_publisher() -> None: From c4975c96af83edd66135e3f25c4edf2fd724025c Mon Sep 17 00:00:00 2001 From: Pavel Tkachyk Date: Mon, 17 Aug 2026 16:39:57 -0400 Subject: [PATCH 2/2] Seal v2.0.3 installation publication history Signed-off-by: Pavel Tkachyk --- docs/extraction-manifest.json | 2 +- scripts/verify_public_plugin_candidate.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/extraction-manifest.json b/docs/extraction-manifest.json index 5a0b21a..b602541 100644 --- a/docs/extraction-manifest.json +++ b/docs/extraction-manifest.json @@ -353,7 +353,7 @@ { "class": "build-and-install", "destination": "scripts/verify_public_plugin_candidate.py", - "destination_sha256": "19f9c6d8770943a5e56bef01885f4d29850e26d89dcc8a7695a8c4190f05a641", + "destination_sha256": "bcb89f657bc719e76f7873f71bf5bd302c06fbedd53a3162e6de64337e01b8db", "source": "scripts/verify_public_plugin_candidate.py", "source_sha256": "4130935d530075fce1758e2e89bd5d973a722e2293b5b1058cfe0d17f326172b", "transformation": "modified_for_standalone" diff --git a/scripts/verify_public_plugin_candidate.py b/scripts/verify_public_plugin_candidate.py index 89732f2..0f8b62a 100644 --- a/scripts/verify_public_plugin_candidate.py +++ b/scripts/verify_public_plugin_candidate.py @@ -288,7 +288,7 @@ "4b444b2583fbdd340b17d279fd169103c57f87a56dece39988d784b311222920" ) TRUSTED_HISTORICAL_BLOB_POLICY_SHA256 = ( - "43ba7c7487a3c7168a96852052fa0fc3c4164c2b402abfde3cce97928d7abad3" + "d18f105fc482c28c9946f3f1bd21235821e9283ef76c48ce04cbfa756c20b09f" ) SCANNER_PATH = "scripts/verify_public_plugin_candidate.py" DESTINATION_MANIFEST_PATH = "docs/extraction-manifest.json"