gabriel / musehub public
feat BREAKING genesis dev
gabriel · 162 days ago · Apr 15, 2026 · Diff

feat(genesis): Phase 4-5 genesis-addressed IDs for all server entities

Phase 4 — service layer: replace uuid4() with compute_*_id() everywhere - musehub_auth.py: compute_identity_id(handle, public_key_b64) - musehub_repository.py: compute_repo_id(owner_identity_id, slug) - musehub_sessions.py: compute_session_id(identity_id, nonce) - musehub_issues.py: compute_issue_id / compute_comment_id - musehub_proposals.py: compute_proposal_id / compute_review_id - All routes and MCP tools updated to pass author_identity_id + domain

Phase 5 — Pydantic validators: @field_validator on all entity ID fields in musehub/models/musehub.py enforces sha256:<64 hex chars> format at the API boundary; invalid IDs raise 422 immediately on deserialization

New files: - musehub/core/genesis.py: all compute_*_id helpers - alembic/versions/0049_widen_commit_id_columns.py - alembic/versions/0050_genesis_addressed_ids.py - tests/test_genesis_ids.py: 43 TDD tests covering all six tiers - tests/test_id_canonical.py, tests/test_object_store_canonical.py

sha256:ad10f6d3966da02981bb920192ae0cce156d5e0ad0dec6f0eefe20d42f41bb4d sha
+299 ~455 −16 symbols
sha256:b0ba6c7074285e4a33882ca8cfc3ab439d4f415b0a963e241965e40b7c713cbd snapshot
+299
symbols added
~455
symbols modified
−16
symbols removed
0
dead code introduced
Semantic Changes 770 symbols
+ branch_labels variable variable branch_labels L24–24
+ depends_on variable variable depends_on L25–25
+ down_revision variable variable down_revision L23–23
+ downgrade function function downgrade L55–79
+ annotations import import annotations L17–17
+ op import import op L20–20
+ sa import import sa L19–19
+ revision variable variable revision L22–22
+ upgrade function function upgrade L28–52
+ _FK_WIDENINGS variable variable _FK_WIDENINGS L79–107
+ _PK_WIDENINGS variable variable _PK_WIDENINGS L67–76
+ branch_labels variable variable branch_labels L63–63
+ depends_on variable variable depends_on L64–64
+ down_revision variable variable down_revision L62–62
+ downgrade function function downgrade L151–187
+ annotations import import annotations L56–56
+ op import import op L59–59
+ sa import import sa L58–58
+ revision variable variable revision L61–61
+ upgrade function function upgrade L110–148
~ deploy/flatten_object_store.py .py 10 symbols added
+ flatten function function flatten L46–89
+ Path import import Path L33–33
+ annotations import import annotations L27–27
+ argparse import import argparse L29–29
+ os import import os L30–30
+ shutil import import shutil L31–31
+ sys import import sys L32–32
+ main function function main L124–144
+ parse_args function function parse_args L36–43
+ update_db function function update_db L92–121
~ musehub/core/genesis.py .py 15 symbols added
+ _SEP variable variable _SEP L35–35
+ _genesis_hash function function _genesis_hash L38–46
+ compute_comment_id function function compute_comment_id L228–240
+ compute_identity_id function function compute_identity_id L53–64
+ compute_issue_id function function compute_issue_id L97–109
+ compute_mist_id function function compute_mist_id L202–212
+ compute_proposal_id function function compute_proposal_id L116–130
+ compute_release_id function function compute_release_id L137–152
+ compute_repo_id function function compute_repo_id L71–90
+ compute_review_id function function compute_review_id L247–259
+ compute_session_id function function compute_session_id L183–195
+ compute_tag_id function function compute_tag_id L159–176
+ annotations import import annotations L30–30
+ hashlib import import hashlib L32–32
+ mist_short_id function function mist_short_id L215–221
~ tests/test_genesis_ids.py .py 82 symbols added
+ TestCanonicalForm class class TestCanonicalForm L87–126
+ test_comment_id_canonical method method test_comment_id_canonical L113–114
+ test_identity_id_canonical method method test_identity_id_canonical L89–90
+ test_issue_id_canonical method method test_issue_id_canonical L95–96
+ test_mist_id_canonical method method test_mist_id_canonical L110–111
+ test_mist_short_id_is_12_chars method method test_mist_short_id_is_12_chars L119–122
+ test_mist_short_id_is_prefix_of_digest method method test_mist_short_id_is_prefix_of_digest L124–126
+ test_proposal_id_canonical method method test_proposal_id_canonical L98–99
+ test_release_id_canonical method method test_release_id_canonical L101–102
+ test_repo_id_canonical method method test_repo_id_canonical L92–93
+ test_review_id_canonical method method test_review_id_canonical L116–117
+ test_session_id_canonical method method test_session_id_canonical L107–108
+ test_tag_id_canonical method method test_tag_id_canonical L104–105
+ TestCrossVerification class class TestCrossVerification L234–250
+ test_release_id_cli_and_hub_agree method method test_release_id_cli_and_hub_agree L240–242
+ test_release_id_cli_returns_canonical method method test_release_id_cli_returns_canonical L248–250
+ test_tag_id_cli_and_hub_agree method method test_tag_id_cli_and_hub_agree L236–238
+ test_tag_id_cli_returns_canonical method method test_tag_id_cli_returns_canonical L244–246
+ TestDerivationChain class class TestDerivationChain L257–309
+ test_changing_issue_changes_comment_id method method test_changing_issue_changes_comment_id L273–278
+ test_changing_owner_changes_repo_id method method test_changing_owner_changes_repo_id L259–264
+ test_changing_proposal_changes_review_id method method test_changing_proposal_changes_review_id L280–285
+ test_changing_repo_changes_issue_id method method test_changing_repo_changes_issue_id L266–271
+ test_identity_repo_issue_comment_chain_is_fully_verifiable method method test_identity_repo_issue_comment_chain_is_fully_verifiable L287–309
+ TestDeterminism class class TestDeterminism L133–191
+ test_all_entity_ids_are_distinct method method test_all_entity_ids_are_distinct L184–191
+ test_different_branches_yield_different_proposal_ids method method test_different_branches_yield_different_proposal_ids L166–169
+ test_different_content_yields_different_mist_ids method method test_different_content_yields_different_mist_ids L181–182
+ test_different_domains_yield_different_repo_ids method method test_different_domains_yield_different_repo_ids L156–159
+ test_different_labels_yield_different_tag_ids method method test_different_labels_yield_different_tag_ids L176–179
+ test_different_pubkeys_yield_different_identity_ids method method test_different_pubkeys_yield_different_identity_ids L146–149
+ test_different_slugs_yield_different_repo_ids method method test_different_slugs_yield_different_repo_ids L151–154
+ test_different_tags_yield_different_release_ids method method test_different_tags_yield_different_release_ids L171–174
+ test_different_timestamps_yield_different_issue_ids method method test_different_timestamps_yield_different_issue_ids L161–164
+ test_identity_id_deterministic method method test_identity_id_deterministic L135–136
+ test_issue_id_deterministic method method test_issue_id_deterministic L142–144
+ test_repo_id_deterministic method method test_repo_id_deterministic L138–140
+ TestSeparatorInjection class class TestSeparatorInjection L198–227
+ test_colon_in_label_is_safe method method test_colon_in_label_is_safe L214–216
+ test_nul_byte_in_slug_does_not_collide method method test_nul_byte_in_slug_does_not_collide L200–208
+ test_path_separator_in_branch_is_safe method method test_path_separator_in_branch_is_safe L218–220
+ test_pipe_in_label_is_safe method method test_pipe_in_label_is_safe L210–212
+ test_sha256_prefix_in_field_is_safe method method test_sha256_prefix_in_field_is_safe L222–227
+ TestServiceLayerGenesisIds class class TestServiceLayerGenesisIds L321–561
+ _async_session method method _async_session L328–357
+ _keypair method method _keypair L359–364
+ test_create_issue_uses_compute_issue_id method async_method test_create_issue_uses_compute_issue_id L435–467
+ test_create_proposal_uses_compute_proposal_id method async_method test_create_proposal_uses_compute_proposal_id L474–518
+ test_create_repo_uses_compute_repo_id method async_method test_create_repo_uses_compute_repo_id L525–561
+ test_register_agent_identity_uses_compute_identity_id method async_method test_register_agent_identity_uses_compute_identity_id L371–396
+ test_upsert_session_uses_compute_session_id method async_method test_upsert_session_uses_compute_session_id L403–428
+ _CANONICAL_RE variable variable _CANONICAL_RE L62–62
+ _COMMENT_ID variable variable _COMMENT_ID L79–79
+ _COMMIT_ID variable variable _COMMIT_ID L75–75
+ _IDENTITY_ID variable variable _IDENTITY_ID L69–69
+ _ISSUE_ID variable variable _ISSUE_ID L72–72
+ _MIST_ID variable variable _MIST_ID L78–78
+ _PROPOSAL_ID variable variable _PROPOSAL_ID L73–73
+ _PUBKEY variable variable _PUBKEY L68–68
+ _RELEASE_ID variable variable _RELEASE_ID L74–74
+ _REPO_ID variable variable _REPO_ID L71–71
+ _REVIEW_ID variable variable _REVIEW_ID L80–80
+ _SESSION_ID variable variable _SESSION_ID L77–77
+ _TAG_ID variable variable _TAG_ID L76–76
+ Path import import Path L36–36
+ annotations import import annotations L32–32
+ cli_compute_release_id import import cli_compute_release_id L57–57
+ cli_compute_tag_id import import cli_compute_tag_id L57–57
+ compute_comment_id import import compute_comment_id L41–41
+ compute_identity_id import import compute_identity_id L41–41
+ compute_issue_id import import compute_issue_id L41–41
+ compute_mist_id import import compute_mist_id L41–41
+ compute_proposal_id import import compute_proposal_id L41–41
+ compute_release_id import import compute_release_id L41–41
+ compute_repo_id import import compute_repo_id L41–41
+ compute_review_id import import compute_review_id L41–41
+ compute_session_id import import compute_session_id L41–41
+ compute_tag_id import import compute_tag_id L41–41
+ mist_short_id import import mist_short_id L41–41
+ pytest import import pytest L38–38
+ re import import re L34–34
+ sys import import sys L35–35
~ tests/test_id_canonical.py .py 64 symbols added
+ TestHashFunctionsReturnCanonicalForm class class TestHashFunctionsReturnCanonicalForm L122–199
+ test_commit_id_is_deterministic method method test_commit_id_is_deterministic L180–185
+ test_compute_commit_id_cli_returns_canonical method method test_compute_commit_id_cli_returns_canonical L147–153
+ test_compute_commit_id_hub_returns_canonical method method test_compute_commit_id_hub_returns_canonical L132–138
+ test_compute_snapshot_id_cli_returns_canonical method method test_compute_snapshot_id_cli_returns_canonical L140–145
+ test_compute_snapshot_id_hub_returns_canonical method method test_compute_snapshot_id_hub_returns_canonical L125–130
+ test_hub_and_cli_commit_id_agree method method test_hub_and_cli_commit_id_agree L163–172
+ test_hub_and_cli_snapshot_id_agree method method test_hub_and_cli_snapshot_id_agree L155–161
+ test_snapshot_id_empty_manifest_returns_canonical method method test_snapshot_id_empty_manifest_returns_canonical L194–199
+ test_snapshot_id_is_deterministic method method test_snapshot_id_is_deterministic L174–178
+ test_snapshot_id_without_dirs_returns_canonical method method test_snapshot_id_without_dirs_returns_canonical L187–192
+ TestWireCommitValidation class class TestWireCommitValidation L204–263
+ test_bare_hex_commit_id_rejected method method test_bare_hex_commit_id_rejected L214–220
+ test_bare_hex_parent_commit_id_rejected method method test_bare_hex_parent_commit_id_rejected L256–263
+ test_bare_hex_snapshot_id_rejected method method test_bare_hex_snapshot_id_rejected L230–236
+ test_canonical_commit_id_accepted method method test_canonical_commit_id_accepted L207–212
+ test_canonical_parent_commit_id_accepted method method test_canonical_parent_commit_id_accepted L238–245
+ test_none_parent_commit_id_accepted method method test_none_parent_commit_id_accepted L247–254
+ test_uuid_commit_id_rejected method method test_uuid_commit_id_rejected L222–228
+ TestWireSnapshotValidation class class TestWireSnapshotValidation L268–291
+ test_bare_hex_snapshot_id_rejected method method test_bare_hex_snapshot_id_rejected L275–278
+ test_canonical_snapshot_id_accepted method method test_canonical_snapshot_id_accepted L271–273
+ test_canonical_snapshot_with_manifest_accepted method method test_canonical_snapshot_with_manifest_accepted L285–291
+ test_uuid_snapshot_id_rejected method method test_uuid_snapshot_id_rejected L280–283
+ _BARE_HEX_64 variable variable _BARE_HEX_64 L66–66
+ _CANONICAL_ID_RE variable variable _CANONICAL_ID_RE L41–41
+ _COMMIT_ID_HUB variable variable _COMMIT_ID_HUB L56–56
+ _DIRS variable variable _DIRS L49–49
+ _MANIFEST variable variable _MANIFEST L45–48
+ _MESSAGE variable variable _MESSAGE L50–50
+ _PARENT_IDS variable variable _PARENT_IDS L52–52
+ _SNAP_ID_HUB variable variable _SNAP_ID_HUB L55–55
+ _TIMESTAMP variable variable _TIMESTAMP L51–51
+ _UUID_ID variable variable _UUID_ID L70–70
+ _VALID_COMMIT_ID variable variable _VALID_COMMIT_ID L61–61
+ _VALID_OBJECT_ID variable variable _VALID_OBJECT_ID L63–63
+ _VALID_PARENT_ID variable variable _VALID_PARENT_ID L62–62
+ _VALID_SNAP_ID variable variable _VALID_SNAP_ID L60–60
+ _make_push_payload function function _make_push_payload L83–117
+ _mp function function _mp L79–80
+ _utc_now function function _utc_now L75–76
+ AsyncClient import import AsyncClient L25–25
+ AsyncSession import import AsyncSession L27–27
+ Path import import Path L21–21
+ ValidationError import import ValidationError L26–26
+ WireCommit import import WireCommit L30–30
+ WireSnapshot import import WireSnapshot L30–30
+ _hashlib import import _hashlib L59–59
+ annotations import import annotations L15–15
+ cli_compute_commit_id import import cli_compute_commit_id L35–35
+ cli_compute_snapshot_id import import cli_compute_snapshot_id L34–34
+ compute_commit_id import import compute_commit_id L29–29
+ compute_snapshot_id import import compute_snapshot_id L29–29
+ create_repo import import create_repo L37–37
+ datetime import import datetime L20–20
+ msgpack import import msgpack L23–23
+ pytest import import pytest L24–24
+ re import import re L17–17
+ sys import import sys L18–18
+ timezone import import timezone L20–20
+ uuid import import uuid L19–19
+ test_push_with_bare_hex_commit_id_returns_422 function async_function test_push_with_bare_hex_commit_id_returns_422 L320–339
+ test_push_with_bare_hex_snapshot_id_returns_422 function async_function test_push_with_bare_hex_snapshot_id_returns_422 L343–362
+ test_push_with_canonical_ids_returns_200 function async_function test_push_with_canonical_ids_returns_200 L297–316
~ tests/test_object_store_canonical.py .py 48 symbols added
+ TestIntegration class class TestIntegration L257–320
+ test_empty_object_roundtrip method async_method test_empty_object_roundtrip L306–320
+ test_multiple_objects_all_roundtrip method async_method test_multiple_objects_all_roundtrip L277–293
+ test_single_object_roundtrip method async_method test_single_object_roundtrip L260–275
+ test_unknown_oid_silently_omitted method async_method test_unknown_oid_silently_omitted L295–304
+ TestPerformance class class TestPerformance L390–408
+ test_10_objects_under_100ms method async_method test_10_objects_under_100ms L393–408
+ TestPersistence class class TestPersistence L349–384
+ test_db_has_no_raw_hex_object_ids method async_method test_db_has_no_raw_hex_object_ids L371–384
+ test_db_stores_sha256_prefixed_object_id method async_method test_db_stores_sha256_prefixed_object_id L352–369
+ TestSchema class class TestSchema L191–251
+ test_fetch_objects_returns_stream_content_type method async_method test_fetch_objects_returns_stream_content_type L194–210
+ test_fetched_object_id_has_sha256_prefix method async_method test_fetched_object_id_has_sha256_prefix L212–226
+ test_push_manifest_uses_sha256_prefix method async_method test_push_manifest_uses_sha256_prefix L228–251
+ TestSecurity class class TestSecurity L414–482
+ test_content_hash_mismatch_rejected_on_push method async_method test_content_hash_mismatch_rejected_on_push L450–482
+ test_raw_hex_oid_in_push_rejected method async_method test_raw_hex_oid_in_push_rejected L417–448
+ TestStress class class TestStress L326–343
+ test_100_objects_all_roundtrip method async_method test_100_objects_all_roundtrip L329–343
+ TestUnit class class TestUnit L137–185
+ test_empty_content_oid method method test_empty_content_oid L154–156
+ test_local_backend_path_uses_prefix_form method method test_local_backend_path_uses_prefix_form L158–169
+ test_s3_key_uses_prefix_form method method test_s3_key_uses_prefix_form L178–185
+ test_safe_id_sanitises_colon method method test_safe_id_sanitises_colon L171–176
+ test_sha256_oid_has_prefix method method test_sha256_oid_has_prefix L140–142
+ test_sha256_oid_hex_is_64_chars method method test_sha256_oid_hex_is_64_chars L144–146
+ test_sha256_oid_known_value method method test_sha256_oid_known_value L148–152
+ _OWNER variable variable _OWNER L42–42
+ _fetch_objects function async_function _fetch_objects L118–131
+ _mp function function _mp L50–51
+ _now function function _now L54–55
+ _parse_stream function function _parse_stream L58–62
+ _push function async_function _push L69–115
+ _sha256_oid function function _sha256_oid L45–47
+ _stream_headers function function _stream_headers L65–66
+ AsyncClient import import AsyncClient L33–33
+ AsyncSession import import AsyncSession L35–35
+ annotations import import annotations L25–25
+ datetime import import datetime L29–29
+ db import import db L37–37
+ factory_create_repo import import factory_create_repo L38–38
+ hashlib import import hashlib L27–27
+ msgpack import import msgpack L31–31
+ pytest import import pytest L32–32
+ select import import select L34–34
+ text import import text L34–34
+ timezone import import timezone L29–29
+ uuid import import uuid L28–28
~ AGENTS.md .md 4 symbols added, 3 symbols modified
+ Testing Rules section Testing Rules L99–110
+ Testing Rules — Read Before Running Any Test section Testing Rules — Read Before Running Any Test L69–99
+ Correct workflow section Correct workflow L74–89
+ Forbidden section Forbidden L89–99
~ deploy/decompress_objects.py .py 2 symbols modified
~ deploy/load-tests/locustfile.py .py 1 symbol modified
~ deploy/repair_objects.py .py 1 symbol modified
~ repair
~ musehub/api/routes/api/auth.py .py 2 symbols modified
~ musehub/auth/request_signing.py .py 2 symbols added, 4 symbols modified
+ _STANDARD_PORTS variable variable _STANDARD_PORTS L64–64
+ _normalise_host function function _normalise_host L102–114
~ musehub/config.py .py 1 symbol modified
~ musehub/mcp/resources.py .py 1 symbol modified
~ musehub/models/musehub.py .py 10 symbols added, 7 symbols modified
+ _check_genesis_ids method method _check_genesis_ids L759–760
+ _check_issue_id method method _check_issue_id L701–702
+ _check_genesis_ids method method _check_genesis_ids L1054–1055
+ _check_proposal_id method method _check_proposal_id L866–867
+ _check_release_id method method _check_release_id L1282–1283
+ _check_repo_id method method _check_repo_id L223–224
+ _check_session_id method method _check_session_id L2216–2217
+ _GENESIS_ID_RE variable variable _GENESIS_ID_RE L25–25
+ _check_genesis_id function function _check_genesis_id L28–33
+ re import import re L8–8
~ musehub/models/wire.py .py 5 symbols added, 5 symbols modified
+ _check_commit_id method method _check_commit_id L105–110
+ _check_parent_commit_id method method _check_parent_commit_id L123–128
+ _check_snapshot_id method method _check_snapshot_id L114–119
+ _check_object_id method method _check_object_id L184–189
+ _check_snapshot_id method method _check_snapshot_id L154–159
~ musehub/services/musehub_auth.py .py 1 symbol added, 2 symbols modified
+ compute_identity_id import import compute_identity_id L47–47
~ musehub/services/musehub_gc.py .py 1 symbol modified
~ run_gc
~ musehub/services/musehub_issues.py .py 2 symbols added, 2 symbols modified
+ compute_comment_id import import compute_comment_id L24–24
+ compute_issue_id import import compute_issue_id L24–24
~ musehub/services/musehub_proposals.py .py 3 symbols added, 5 symbols modified
+ compute_comment_id import import compute_comment_id L28–28
+ compute_proposal_id import import compute_proposal_id L28–28
+ compute_review_id import import compute_review_id L28–28
~ musehub/services/musehub_repository.py .py 3 symbols added, 2 symbols modified
+ get_identity_id_for_handle function async_function get_identity_id_for_handle L309–314
+ compute_repo_id import import compute_repo_id L23–23
+ compute_session_id import import compute_session_id L23–23
~ musehub/services/musehub_sessions.py .py 1 symbol added, 1 symbol modified
+ compute_session_id import import compute_session_id L23–23
~ src/ts/pages/user-profile.ts .ts 1 symbol removed, 6 symbols modified
− loadStarsTab function async_function loadStarsTab L459–468
~ tests/conftest.py .py 2 symbols modified
~ tests/factories.py .py 1 symbol modified
~ tests/test_clone_integrity.py .py 2 symbols added, 1 symbol removed, 3 symbols modified
− uuid import import uuid L30–30 → moved to tests/test_security_hardening.py
+ compute_commit_id import import compute_commit_id L39–39
+ compute_snapshot_id import import compute_snapshot_id L39–39
~ tests/test_encoding_roundtrip.py .py 5 symbols added, 5 symbols removed
− _bare_hex function function _bare_hex L43–45
− test_delta_zlib_bare_hex_stored_as_plain_bytes function async_function test_delta_zlib_bare_hex_stored_as_plain_bytes L245–316
− test_encoding_none_bare_hex_stored_correctly function async_function test_encoding_none_bare_hex_stored_correctly L324–370
− test_zlib_bare_hex_blob_view_serves_plain_text function async_function test_zlib_bare_hex_blob_view_serves_plain_text L180–237
− test_zlib_bare_hex_stored_as_plain_bytes function async_function test_zlib_bare_hex_stored_as_plain_bytes L112–172
+ _sha256_oid function function _sha256_oid L44–46
+ test_delta_zlib_stored_as_plain_bytes function async_function test_delta_zlib_stored_as_plain_bytes L248–319
+ test_encoding_none_stored_correctly function async_function test_encoding_none_stored_correctly L327–373
+ test_zlib_blob_view_serves_plain_text function async_function test_zlib_blob_view_serves_plain_text L181–240
+ test_zlib_stored_as_plain_bytes function async_function test_zlib_stored_as_plain_bytes L113–173
~ tests/test_msign_request_signing.py .py 9 symbols added, 5 symbols removed, 16 symbols modified
− test_first_line_is_method method method test_first_line_is_method L122–124
− test_format_is_four_lines method method test_format_is_four_lines L117–120
− test_fourth_line_is_sha256_hex_of_body method method test_fourth_line_is_sha256_hex_of_body L136–140
− test_second_line_is_path method method test_second_line_is_path L126–129
− test_third_line_is_timestamp method method test_third_line_is_timestamp L131–134
+ test_different_host_produces_different_bytes method method test_different_host_produces_different_bytes L161–165
+ test_fifth_line_is_timestamp method method test_fifth_line_is_timestamp L142–145
+ test_first_line_is_algorithm method method test_first_line_is_algorithm L123–125
+ test_format_is_six_lines method method test_format_is_six_lines L118–121
+ test_fourth_line_is_path method method test_fourth_line_is_path L137–140
+ test_second_line_is_method method method test_second_line_is_method L127–130
+ test_sixth_line_is_sha256_hex_of_body method method test_sixth_line_is_sha256_hex_of_body L147–151
+ test_third_line_is_host method method test_third_line_is_host L132–135
+ test_returns_none_for_missing_alg method method test_returns_none_for_missing_alg L202–204
~ tests/test_musehub_sitemap.py .py 1 symbol modified
~ tests/test_security_hardening.py .py 2 symbols added, 5 symbols modified
+ hashlib import import hashlib L17–17
+ uuid import import uuid L19–19 ← moved from tests/test_clone_integrity.py
~ tests/test_storage_backends.py .py 55 symbols modified
~ tests/test_wire_protocol.py .py 2 symbols added, 35 symbols modified
+ _sha256_id function function _sha256_id L39–41
+ hashlib import import hashlib L16–16
← Older Oldest on dev
All commits
Newer → Latest on dev

0 comments

No comments yet. Be the first to start the discussion.

To add a comment, use the Muse CLI: muse hub commit comment sha256:ad10f6d3966da02981bb920192ae0cce156d5e0ad0dec6f0eefe20d42f41bb4d --body "your comment"