Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
213 commits
Select commit Hold shift + click to select a range
9a6a3b8
test(release): reproduce desktop version identity drift
seonghobae Sep 1, 2026
6749f4e
test(release): narrow RED to release version gate
seonghobae Sep 1, 2026
261a9a2
feat(release): add fail-closed version identity guard
seonghobae Sep 1, 2026
8d95854
fix(release): enforce version identity in preflight harness
seonghobae Sep 1, 2026
164f344
test(release): reject ambiguous VERSION authority
seonghobae Sep 1, 2026
f3ebe4d
fix(release): parse VERSION as a single authority line
seonghobae Sep 1, 2026
d8efdf7
test(release): require identity gate before publication
seonghobae Sep 1, 2026
96d6f16
fix(release): gate artifact publication on version identity
seonghobae Sep 1, 2026
06ef13e
fix(release): keep workflow contract dependency-free
seonghobae Sep 1, 2026
3ecadd7
refactor(release): use semantic identity names
seonghobae Sep 1, 2026
b0d5ecb
test(release): use semantic release-identity names
seonghobae Sep 1, 2026
dfbcbca
docs(release): document identity-gate security boundary
seonghobae Sep 2, 2026
764e06c
test(release): require platform trust before publication
seonghobae Sep 2, 2026
13da983
feat(release): verify native signing and notarization evidence
seonghobae Sep 2, 2026
8de728b
fix(release): block tag packaging without native trust
seonghobae Sep 2, 2026
d33bb96
test(release): exercise tag packaging trust boundary
seonghobae Sep 2, 2026
b0bfbd2
Merge protected develop into trusted release owner
seonghobae Sep 4, 2026
397eac3
Merge current protected develop into Distribution owner
seonghobae Sep 14, 2026
9361e50
test(release): require commercial model artifact admission
seonghobae Sep 14, 2026
516189a
fix(release): add immutable model artifact admission guard
seonghobae Sep 14, 2026
b4234e6
build(release): keep upstream htdemucs commercially blocked
seonghobae Sep 14, 2026
9b81b97
test(release): bind loader policy evidence to admitted model
seonghobae Sep 14, 2026
4dd8d76
fix(release): gate tag builds on model admission
seonghobae Sep 14, 2026
9be81ba
test(release): exercise tag model admission through preflight
seonghobae Sep 14, 2026
0fdadef
test(release): keep one composed model admission preflight
seonghobae Sep 14, 2026
788e8bd
repair(restack): restore protected develop before Distribution delta
seonghobae Sep 14, 2026
1313fba
fix(release): gate tag artifact writes on release preflight
seonghobae Sep 14, 2026
d63a954
test(release): bind preflight to artifact packaging boundary
seonghobae Sep 14, 2026
a6e48e0
test(release): enforce blocked model at packaging preflight
seonghobae Sep 14, 2026
0f1d1ca
test(release): require backing bytes for model evidence digests
seonghobae Sep 14, 2026
3e35c93
fix(release): bind model admission to evidence bytes
seonghobae Sep 14, 2026
3ab03f0
test(release): exercise model evidence byte bindings
seonghobae Sep 14, 2026
b33958c
test(release): require exact immutable release receipt
seonghobae Sep 14, 2026
73a213c
fix(release): bind trusted packages into exact release receipt
seonghobae Sep 14, 2026
6d63fbf
fix(release): keep receipt value object import-safe
seonghobae Sep 14, 2026
6b0c520
test(release): cover receipt admission edge cases
seonghobae Sep 14, 2026
838b675
docs(release): trace exact package receipt boundary
seonghobae Sep 14, 2026
59e5b7c
docs(release): correct updater reference attribution
seonghobae Sep 14, 2026
3d09416
test(release): require admitted model inventory binding
seonghobae Sep 14, 2026
7a8664d
fix(release): bind admitted model to component inventory
seonghobae Sep 14, 2026
0cd9a59
test(release): keep admitted fixtures inventory-complete
seonghobae Sep 14, 2026
38712e8
test(release): add updater admission RED
seonghobae Sep 14, 2026
2cd667c
fix(release): add fail-closed updater policy guard
seonghobae Sep 14, 2026
50ca2a8
fix(release): record blocked updater authority
seonghobae Sep 14, 2026
10cf39d
fix(release): compose updater admission with tag preflight
seonghobae Sep 14, 2026
9e00fee
test(release): repair updater fixture reuse
seonghobae Sep 14, 2026
0b565ba
docs(release): trace updater admission boundary
seonghobae Sep 14, 2026
8843a30
test(release): require updater runtime wiring before admission
seonghobae Sep 14, 2026
9869d32
fix(release): bind updater admission to compiled runtime wiring
seonghobae Sep 14, 2026
6d91f7c
test(release): project admitted updater fixtures through runtime wiring
seonghobae Sep 14, 2026
b535013
docs(traceability): bind updater admission to runtime wiring evidence
seonghobae Sep 14, 2026
421aaee
test(release): require updater bundles and signatures in release evid…
seonghobae Sep 14, 2026
0e01272
fix(release): bind Tauri updater bundles and signatures to release re…
seonghobae Sep 14, 2026
0fa7238
docs(traceability): bind updater artifact bytes to release receipt
seonghobae Sep 14, 2026
45772bf
docs(traceability): include exact updater artifact receipt boundary
seonghobae Sep 14, 2026
b948e70
test(release): require updater evidence through immutable publication…
seonghobae Sep 14, 2026
ef17d4a
fix(release): preserve updater evidence across artifact extraction
seonghobae Sep 14, 2026
6d50e44
fix(release): re-admit updater receipts before immutable publication
seonghobae Sep 14, 2026
a456b1a
fix(release): make target receipts collision-free across publication
seonghobae Sep 14, 2026
4ab309f
test(release): use target-qualified receipts across publication
seonghobae Sep 14, 2026
63774aa
test(release): model complete receipt-bound updater publication set
seonghobae Sep 14, 2026
03555ee
test(release): reproduce updater manifest publication gap
seonghobae Sep 14, 2026
340b476
fix(release): bind updater manifest to receipt-authorized bytes
seonghobae Sep 14, 2026
4d6f7cb
fix(release): publish receipt-bound updater manifest
seonghobae Sep 14, 2026
64fbd14
fix(release): preserve exact updater signature text
seonghobae Sep 14, 2026
889554d
test(release): cover manifest publication boundary cleanly
seonghobae Sep 14, 2026
f0d6dd5
docs(release): trace receipt-bound updater manifest publication
seonghobae Sep 14, 2026
db4ad06
test(release): reproduce hosted asset re-verification gap
seonghobae Sep 14, 2026
e022794
fix(release): re-admit downloaded hosted release assets
seonghobae Sep 14, 2026
3c9221b
fix(release): re-verify draft and published release bytes
seonghobae Sep 14, 2026
3412a19
test(release): format hosted re-verification coverage
seonghobae Sep 14, 2026
4c1dfe9
docs(release): trace hosted release byte re-verification
seonghobae Sep 14, 2026
0f13ef0
test(release): require immutable release attestation gate
seonghobae Sep 14, 2026
b65f00c
fix(release): verify immutable release attestation
seonghobae Sep 14, 2026
d6cc359
docs(release): trace immutable release attestation gate
seonghobae Sep 14, 2026
57ced89
test(release): require updater manifest security metadata
seonghobae Sep 14, 2026
21ee4ff
fix(release): bind updater security metadata to receipts
seonghobae Sep 14, 2026
209f58e
docs(release): trace updater security metadata boundary
seonghobae Sep 14, 2026
857e1e9
test(release): cover updater policy metadata admission
seonghobae Sep 14, 2026
4467a9e
test(distribution): require Rust updater lifecycle core
seonghobae Sep 14, 2026
1339cfd
feat(distribution): add updater lifecycle Rust core crate
seonghobae Sep 14, 2026
0fbb2e8
build(distribution): lock updater lifecycle core
seonghobae Sep 14, 2026
42fdeed
fix(distribution): enforce updater anti-replay and rollback decisions
seonghobae Sep 14, 2026
cd25fab
docs(distribution): trace anti-replay rollback decision core
seonghobae Sep 14, 2026
d80a477
chore(distribution): deny warnings and missing rustdoc
seonghobae Sep 14, 2026
a0a9eec
docs(architecture): register Distribution update decision core
seonghobae Sep 14, 2026
9df9e61
docs(product): establish commercial technical gap baseline
seonghobae Sep 14, 2026
fa5690b
test(distribution): require durable highest-seen state suite
seonghobae Sep 14, 2026
f07f35e
feat(distribution): establish highest-seen state crate
seonghobae Sep 14, 2026
30159e0
build(distribution): lock highest-seen state graph
seonghobae Sep 14, 2026
95889b6
feat(distribution): persist replay authority as bounded append log
seonghobae Sep 14, 2026
05a8dc9
docs(distribution): trace durable updater freshness state
seonghobae Sep 14, 2026
9a481cc
docs(product): record durable updater-state progress
seonghobae Sep 14, 2026
fb1ac16
fix(distribution): disambiguate bounded state read
seonghobae Sep 14, 2026
6826c92
docs(architecture): register durable Distribution state owner
seonghobae Sep 14, 2026
e525aa1
test(distribution): require authenticated runtime admission suite
seonghobae Sep 14, 2026
5c95912
feat(distribution): add runtime admission crate manifest
seonghobae Sep 14, 2026
b9f72be
build(distribution): lock runtime path dependency graph
seonghobae Sep 14, 2026
85db601
feat(distribution): bound raw updater metadata as provisional input
seonghobae Sep 14, 2026
def74ef
refactor(distribution): keep provisional runtime admission stateless
seonghobae Sep 14, 2026
418c68d
build(distribution): minimize provisional runtime lock graph
seonghobae Sep 14, 2026
1c52911
docs(distribution): correct raw updater metadata trust boundary
seonghobae Sep 14, 2026
d0bdea0
docs(product): expose updater metadata-authentication gap
seonghobae Sep 14, 2026
8533403
docs(architecture): separate provisional updater metadata from authority
seonghobae Sep 14, 2026
59bc8c8
fix(updater): pin provisional release download namespace
seonghobae Sep 14, 2026
daad6e5
fix(updater): keep URL admission Rust-stable
seonghobae Sep 14, 2026
e25c3f1
docs(updater): trace pinned release URL admission
seonghobae Sep 14, 2026
1e1f1c2
test(distribution): require bounded updater download contract
seonghobae Sep 14, 2026
f183c0c
feat(distribution): add bounded updater artifact streaming
seonghobae Sep 14, 2026
19c5983
docs(distribution): trace bounded updater streaming boundary
seonghobae Sep 14, 2026
21f3bee
docs(product): make bounded updater download gap code-current
seonghobae Sep 14, 2026
539fbe2
docs(architecture): add bounded updater download owner
seonghobae Sep 14, 2026
dcc04b7
test(distribution): require crash-safe updater staging sink
seonghobae Sep 14, 2026
ed079fd
feat(distribution): add exclusive updater staging sink
seonghobae Sep 14, 2026
7620248
test(distribution): cover updater staging failure cleanup
seonghobae Sep 14, 2026
00825be
docs(distribution): trace exclusive updater staging lifecycle
seonghobae Sep 14, 2026
e485b3a
docs(product): record updater staging boundary
seonghobae Sep 14, 2026
a956bcf
test(distribution): remove unverified sealed artifacts on drop
seonghobae Sep 14, 2026
e76abdd
fix(distribution): clean sealed artifacts until trust promotion
seonghobae Sep 14, 2026
2909133
docs(distribution): trace sealed-artifact cleanup before trust promotion
seonghobae Sep 14, 2026
a065ceb
docs(product): keep sealed updater bytes provisional
seonghobae Sep 14, 2026
56aa746
test(distribution): require sealed read-only descriptor stream
seonghobae Sep 14, 2026
13ca9b7
test(distribution): stop depending on writable sealed handle
seonghobae Sep 14, 2026
6144302
fix(distribution): withhold writable sealed artifact handle
seonghobae Sep 14, 2026
fdd9705
docs(traceability): bind sealed updater reads to descriptor
seonghobae Sep 14, 2026
5568e22
docs(product): keep sealed updater descriptor read-only
seonghobae Sep 14, 2026
f6723cf
docs(architecture): withhold sealed updater write capability
seonghobae Sep 14, 2026
1c8d83d
docs(architecture): restore sources and narrow sealed reader capability
seonghobae Sep 14, 2026
5713689
docs(architecture): restore exact verification wording
seonghobae Sep 14, 2026
e1274be
test(distribution): RED bound sealed reads to admitted bytes
seonghobae Sep 14, 2026
c451096
fix(distribution): cap sealed verifier reads at admitted bytes
seonghobae Sep 14, 2026
e294147
test(distribution): reject sealed descriptor truncation
seonghobae Sep 14, 2026
f6b376a
docs(distribution): trace sealed reader byte-bound repair
seonghobae Sep 14, 2026
56d215e
docs(product): keep sealed verifier resource bound code-current
seonghobae Sep 14, 2026
9f7bddd
test(distribution): require admitted artifact transport binding
seonghobae Sep 15, 2026
663affc
fix(distribution): bind admitted artifact transport fields
seonghobae Sep 15, 2026
ed7426f
docs(distribution): trace admitted transport binding
seonghobae Sep 15, 2026
9c95c71
docs(product): align updater transport gap baseline
seonghobae Sep 15, 2026
46c4cba
docs(architecture): bind updater transport metadata owner
seonghobae Sep 15, 2026
9d1dc2f
test(release): reject runtime-incompatible release versions
seonghobae Sep 15, 2026
e268c9b
fix(release): align release version grammar with updater core
seonghobae Sep 15, 2026
97f9c2a
docs(traceability): bind stable release version grammar
seonghobae Sep 15, 2026
6cee7a6
docs(product): record stable release grammar invariant
seonghobae Sep 15, 2026
1cf9656
test(release): reject version components beyond u64
seonghobae Sep 15, 2026
1c44f25
fix(release): align stable version range with runtime
seonghobae Sep 15, 2026
c2fd0cd
docs(traceability): close stable version range drift
seonghobae Sep 15, 2026
ba426b4
docs(product): record stable version range invariant
seonghobae Sep 15, 2026
6e6ebe2
feat(distribution): add updater transport crate
seonghobae Sep 15, 2026
5f29863
build(distribution): lock transport owner graph
seonghobae Sep 15, 2026
2819481
feat(distribution): add transport response boundary
seonghobae Sep 15, 2026
8f39dfc
test(distribution): require admitted GitHub release redirect
seonghobae Sep 15, 2026
1b4f7a0
test(distribution): gate transport contract in root suite
seonghobae Sep 15, 2026
4964c3c
fix(distribution): admit one-hop GitHub release asset redirects
seonghobae Sep 15, 2026
d424dd8
docs(distribution): trace updater transport policy
seonghobae Sep 15, 2026
adc52ef
docs(product): align distribution transport gap baseline
seonghobae Sep 15, 2026
2e77173
docs(architecture): register updater transport boundary
seonghobae Sep 15, 2026
8313e9f
test(distribution): reject malformed Tauri signature envelopes
seonghobae Sep 15, 2026
6e5e42f
fix(distribution): validate Tauri signature envelope before network
seonghobae Sep 15, 2026
03c1314
test(release): reject non-base64 updater signatures
seonghobae Sep 15, 2026
2c7c772
fix(release): enforce Tauri signature envelope before publication
seonghobae Sep 15, 2026
fd906e2
docs(distribution): trace signature-envelope admission
seonghobae Sep 15, 2026
0e318ef
docs(product): align updater signature-envelope gap
seonghobae Sep 15, 2026
2f5af3e
docs(architecture): align updater signature-envelope ownership
seonghobae Sep 15, 2026
e376325
test(distribution): reject encoded updater response bodies
seonghobae Sep 15, 2026
606095e
fix(distribution): reject transformed updater response bodies
seonghobae Sep 15, 2026
f616421
docs(distribution): trace exact response-byte framing admission
seonghobae Sep 15, 2026
80fdc39
docs(product): record exact-byte updater response framing
seonghobae Sep 15, 2026
c3dbebe
test(distribution): redact redirect queries in diagnostics
seonghobae Sep 15, 2026
be91505
fix(distribution): redact redirect query data from diagnostics
seonghobae Sep 15, 2026
6b8cabb
docs(distribution): trace updater diagnostic redaction
seonghobae Sep 15, 2026
935266a
test(distribution): bound updater signature debug output
seonghobae Sep 15, 2026
1a4e8f5
fix(distribution): bound signature diagnostics
seonghobae Sep 15, 2026
b290bf0
docs(distribution): trace bounded signature diagnostics
seonghobae Sep 15, 2026
027ba14
test(distribution): reject provisional signature debug exposure
seonghobae Sep 15, 2026
90855cc
fix(distribution): redact provisional signature diagnostics
seonghobae Sep 15, 2026
bd17041
docs(distribution): record provisional diagnostic redaction
seonghobae Sep 15, 2026
93526ae
docs(gap): keep updater diagnostics buyer truth current
seonghobae Sep 15, 2026
5b0ddb5
test(distribution): require restart recovery for stale staging artifact
seonghobae Sep 15, 2026
b7a1839
fix(distribution): reclaim stale unverified staging artifact on restart
seonghobae Sep 15, 2026
e1b4a81
docs(distribution): trace stale staging restart recovery
seonghobae Sep 15, 2026
84d4a7b
docs(product): record updater staging restart recovery boundary
seonghobae Sep 15, 2026
dcd7a80
docs(distribution): align bounded staging with restart recovery
seonghobae Sep 15, 2026
74565b8
repair(distribution): return product baseline to canonical owner
seonghobae Sep 15, 2026
82843b4
test(distribution): reject reclaiming active staging attempts
seonghobae Sep 15, 2026
40cd754
fix(distribution): lease staging namespace before stale recovery
seonghobae Sep 15, 2026
ebf9428
test(distribution): account for persistent staging lease sentinel
seonghobae Sep 15, 2026
d2d1872
test(distribution): cover sealed lease and lease symlink boundary
seonghobae Sep 15, 2026
ebefa23
docs(distribution): trace active staging lease recovery
seonghobae Sep 15, 2026
9046e90
docs(distribution): make bounded staging lease code-current
seonghobae Sep 15, 2026
752b534
test(distribution): avoid platform-specific reads under staging lease
seonghobae Sep 15, 2026
c30167d
docs(distribution): record cross-platform staging lease fixture
seonghobae Sep 15, 2026
41afd2a
test(distribution): require staging lease contracts on shipped OS fam…
seonghobae Sep 15, 2026
cfb3ec1
ci(distribution): gate staging lease tests on Windows macOS and Linux
seonghobae Sep 15, 2026
137d162
docs(distribution): require cross-platform staging lease evidence
seonghobae Sep 15, 2026
44265a0
test(distribution): prove staging lease across real processes
seonghobae Sep 15, 2026
a999376
docs(distribution): trace real-process staging lease coverage
seonghobae Sep 15, 2026
af89337
test(release): red for descriptor-bound identity inputs
seonghobae Sep 15, 2026
42d34b5
fix(release): bind identity reads to stable descriptors
seonghobae Sep 15, 2026
0ef8912
docs(release): trace descriptor-bound identity admission
seonghobae Sep 15, 2026
68f1bb5
test(release): reject nonstandard JSON constants in identity inputs
seonghobae Sep 15, 2026
494aa0f
fix(release): require strict standard JSON identity metadata
seonghobae Sep 15, 2026
6808f29
docs(traceability): record strict JSON release identity admission
seonghobae Sep 15, 2026
8d56ab1
test(distribution): reject malformed nonselected signature envelope
seonghobae Sep 15, 2026
4e28d0c
fix(distribution): validate all updater signature envelopes
seonghobae Sep 15, 2026
9b691d7
refactor(distribution): keep signature syntax in metadata owner
seonghobae Sep 15, 2026
5b85e03
test(distribution): assert signature envelope owner boundary
seonghobae Sep 15, 2026
89f97a2
docs(distribution): make metadata owner authoritative for signature e…
seonghobae Sep 15, 2026
eb29922
test(distribution): cover signature envelope padding bounds
seonghobae Sep 15, 2026
a62b9ca
docs(architecture): align updater signature-envelope ownership
seonghobae Sep 15, 2026
26ff403
test(distribution): use admitted signature envelopes
seonghobae Sep 15, 2026
11a5a47
test(distribution): bind redirect decisions to policy identity
seonghobae Sep 15, 2026
35b851e
fix(distribution): bind redirect state to policy identity
seonghobae Sep 15, 2026
3f7daa8
docs(distribution): trace redirect policy binding repair
seonghobae Sep 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 49 additions & 3 deletions .github/workflows/build-baseline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -410,8 +410,17 @@ jobs:
bandscope-sbom.cdx.json
supply-chain/supplemental-component-inventory.json
- name: Validate release asset set
run: python3 scripts/release/select_release_assets.py --output release-assets.txt
- name: Create draft release with complete assets, then publish
run: python3 scripts/release/select_release_assets.py --output release-artifacts.txt
- name: Build receipt-bound updater manifest
run: |
python3 scripts/release/build_updater_manifest.py \
--git-sha "${{ github.sha }}" \
--repository "${{ github.repository }}" \
--server-url "${{ github.server_url }}" \
--output latest.json
cp release-artifacts.txt release-assets.txt
printf '%s\n' latest.json >> release-assets.txt
- name: Create draft release, re-verify hosted bytes, then publish
env:
GH_TOKEN: ${{ secrets.BANDSCOPE_RELEASE_TOKEN }}
RELEASE_TAG: ${{ github.ref_name }}
Expand All @@ -425,7 +434,16 @@ jobs:
echo "Release $RELEASE_TAG already exists; immutable release assets must be attached before publication."
exit 1
fi
python3 scripts/release/select_release_assets.py --input release-assets.txt
python3 scripts/release/select_release_assets.py --input release-artifacts.txt
python3 scripts/release/build_updater_manifest.py \
--git-sha "${{ github.sha }}" \
--repository "${{ github.repository }}" \
--server-url "${{ github.server_url }}" \
--output latest.json \
--check
cp release-artifacts.txt expected-release-assets.txt
printf '%s\n' latest.json >> expected-release-assets.txt
cmp -s expected-release-assets.txt release-assets.txt
mapfile -t release_assets < release-assets.txt
(( ${#release_assets[@]} > 0 ))
gh release create "$RELEASE_TAG" \
Expand All @@ -435,4 +453,32 @@ jobs:
--title "BandScope ${RELEASE_TAG#v}" \
--verify-tag \
--repo "${{ github.repository }}"

rm -rf draft-release-download
mkdir draft-release-download
gh release download "$RELEASE_TAG" \
--dir draft-release-download \
--repo "${{ github.repository }}"
python3 scripts/release/verify_hosted_release_assets.py \
--local-root . \
--hosted-root draft-release-download \
--asset-list release-assets.txt

gh release edit "$RELEASE_TAG" --draft=false --repo "${{ github.repository }}"

rm -rf published-release-download
mkdir published-release-download
gh release download "$RELEASE_TAG" \
--dir published-release-download \
--repo "${{ github.repository }}"
python3 scripts/release/verify_hosted_release_assets.py \
--local-root . \
--hosted-root published-release-download \
--asset-list release-assets.txt

gh release verify "$RELEASE_TAG" --repo "${{ github.repository }}"
while IFS= read -r asset; do
[ -n "$asset" ] || continue
gh release verify-asset "$RELEASE_TAG" "$asset" \
--repo "${{ github.repository }}"
done < release-assets.txt
24 changes: 23 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,31 @@ jobs:
- name: Reject manifest or lockfile drift
run: git diff --exit-code -- package.json package-lock.json

distribution-download-platform:
name: gate / ci / distribution-download / ${{ matrix.os }}
needs: lock-validation
strategy:
fail-fast: false
matrix:
os:
- ubuntu-latest
- windows-2025
- macos-15
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false
- name: Install stable Rust toolchain
run: rustup toolchain install stable --profile minimal
- name: Test Distribution download staging and lease contracts
run: cargo +stable test --manifest-path apps/desktop/distribution-download/Cargo.toml --locked --all-targets

verify:
name: ci / build-and-test
needs: lock-validation
needs:
- lock-validation
- distribution-download-platform
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
Expand Down
28 changes: 26 additions & 2 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ARCHITECTURE.md

Last updated: 2026-03-11
Last updated: 2026-09-15

## Brand source

Expand Down Expand Up @@ -58,11 +58,34 @@ Last updated: 2026-03-11
## Repository map

- `apps/desktop` - desktop shell and user-facing React UI
- `apps/desktop/distribution-core` - Tauri-independent Rust security policy for updater release identity, anti-replay, target compatibility, and project-schema-aware rollback decisions
- `apps/desktop/distribution-runtime` - stateless Rust admission boundary for untrusted Tauri updater JSON; validates the complete four-target document including each platform's canonical standard-base64 outer signature envelope, then returns provisional metadata with the selected target's exact admitted URL/signature and cannot mutate freshness state
- `apps/desktop/distribution-transport` - deterministic Rust response-state bridge from the strict provisional target projection to bounded updater staging; consumes metadata-owner signature syntax guarantees and owns exact effective-URL checks plus one-hop release-asset redirect admission, but not sockets, TLS, metadata authentication, minisign verification or installation
- `apps/desktop/distribution-download` - network-library-independent Rust streaming/staging boundary for updater artifacts; owns expected-size/content-length/chunk/cumulative limits, exclusive temporary artifact lifecycle, cleanup-on-drop and read-only descriptor-bound verifier access, but not HTTP, signatures, digests or installation
- `apps/desktop/distribution-state` - Distribution-owned bounded append/sync log for the highest authenticated updater identity; consumes `distribution-core` identity and never project bytes
- `packages/shared-types` - stable cross-layer types shared by the UI and orchestration layer
- `services/analysis-engine` - Python analysis service for source separation and music analysis
- `scripts/harness` - fail-fast repo verification
- `scripts/checks` - small doc and structure checks

## Distribution/update bounded context

- Distribution owns commercial release identity, native signing/notarization admission, updater policy, immutable publication evidence, bounded updater artifact transport/storage admission, highest-seen update freshness state, and last-known-good installer recovery decisions.
- `apps/desktop/distribution-core` contains deterministic security decisions only. It does not fetch metadata, verify Tauri signatures, write project data, run installers, or manufacture signing/key authority.
- `apps/desktop/distribution-runtime` admits the current static updater JSON only as bounded provisional remote input. It rejects duplicate/unknown members, unexpected targets, mutable release URLs, invalid release-identity syntax, and any supported platform signature that is not a bounded canonical RFC 4648 standard-base64 outer envelope; retains the selected target's canonical URL/signature from that same strict parse for later transport consumption; and projects the fixed app-owned highest-seen path without creating or writing it. It deliberately has no `distribution-state` dependency, and retained transport fields remain provisional rather than authenticated authority.
- `apps/desktop/distribution-transport` consumes only that already-selected provisional projection and admits updater transport state without reparsing `raw_json` or duplicating signature-envelope syntax. A direct `200` must report the exact canonical initial URL. GitHub release-asset `302` handling is explicit and limited to one HTTPS hop to the current `release-assets.githubusercontent.com` egress allowlist; the follow-up must terminate in `200` at the exact admitted Location and redirect chaining fails closed. The CDN hostname is a product allowlist, not a claim that GitHub guarantees it permanently. The crate has no HTTP client, socket, installer, metadata-authentication, minisign-verification or freshness-state capability.
- Publication mirrors that outer signature-envelope contract after exact receipt binding: `scripts/release/build_updater_manifest.py` requires `.sig` bytes to be canonical standard base64 and the decoded envelope payload to be UTF-8 before static updater JSON can be emitted. This is publication admission only and does not replace Tauri's updater signature verification.
- `apps/desktop/distribution-download` owns the pure streaming/staging primitive used before artifact trust is established. It enforces a 2 GiB artifact ceiling, exact optional `Content-Length`, 1 MiB maximum caller chunk, cumulative overrun rejection before sink write, sink-error poisoning, exact-length completion, exclusive app-owned staging and cleanup-on-drop. A sealed artifact remains provisional; downstream verification reads the exact still-open descriptor through a positional `Read` wrapper and cannot obtain the underlying write-capable staging `File` through the public API. It does not perform network I/O, authenticate metadata, verify signatures/digests, run installers or mutate freshness state. Commercial completion requires the production HTTP adapter to disable implicit redirects, report response state through `distribution-transport`, and route actual response chunks through this boundary rather than relying on Tauri's full-response buffering.
- `apps/desktop/distribution-state` persists only the highest authenticated release identity as a bounded append-only log. It revalidates committed identities, rejects local version regression/equivocation, synchronizes accepted appends, and recovers only a syntactically valid torn final-record prefix; it does not own Tauri networking/signature verification, installer execution, or project persistence.
- Tauri updater signatures authenticate downloaded updater artifact bytes. They do not, by themselves, authenticate the whole `Update.raw_json` response or BandScope's `sourceCommit`/digest extensions. Remote metadata therefore stays provisional until a canonical metadata-authentication path binds its release identity to trusted authority.
- Only after metadata authentication and updater artifact signature/digest/size binding may exact `version`, `sourceCommit`, updater SHA-256, target, and compatibility floor enter `distribution-core` and `distribution-state` as freshness authority.
- Stable-channel automatic update decisions use canonical numeric `MAJOR.MINOR.PATCH`. Prerelease/build ordering is not approximated; a future beta channel requires a separate ADR and canonical SemVer implementation.
- A release older than locally persisted highest-seen authenticated metadata is replay, and the same version with a different source commit or updater digest is equivocation. Neither may be silently downgraded into a normal update offer.
- Highest-seen release identity belongs to Distribution-owned app state and is recorded only after its metadata identity has authenticated authority; installation completion is not required, but syntactically valid remote JSON alone is insufficient. Project Persistence remains owner of project bytes and project-schema truth.
- Automatic rollback may use only a previously authenticated known-good installer whose version is older than the current installation and whose declared reader can open the current on-disk project schema. The decision core does not bypass project recovery or schema ownership.
- `release/updater-policy.json` remains fail-closed while organization-approved updater key/production endpoint authority is absent. No source code or test fixture is production authority.
- Traceability and claim boundaries live in `docs/traceability/updater-release-admission.md`, `docs/traceability/release-artifact-receipt.md`, `docs/traceability/updater-security-metadata.md`, `docs/traceability/updater-bounded-download.md`, and `docs/traceability/updater-transport-policy.md`.

## Product capability scope

- BandScope is not only a shell around chord labels, stems, and ranges.
Expand Down Expand Up @@ -96,10 +119,11 @@ Last updated: 2026-03-11
## Harness decisions

- The harness uses `npm` workspaces for JavaScript/TypeScript and `uv` for Python.
- The desktop app is scaffolded as `Tauri + Vite + React`, but initial verification keeps Rust packaging out of the default quickcheck path.
- The desktop app is scaffolded as `Tauri + Vite + React`. Full Tauri packaging remains outside the default quickcheck path, while security-critical Tauri-independent Rust bounded-context suites may be invoked from repository tests through a narrow validation boundary.
- The desktop shell uses an explicit Tauri CSP that only allows self-hosted assets, inline styles, Tauri IPC, and loopback development traffic.
- Mechanical gates focus on lint, typecheck, unit tests, coverage for Python, and documentation presence.
- Python quality gates also require 100% docstring coverage via `package.json` script `check:python-docstrings`, enforced with Ruff rules `D100` through `D107` across tracked packages, modules, classes, nested classes, functions, methods (including `__init__`), `services/analysis-engine` tests, and repo-owned Python scripts.
- Distribution `distribution-core`, `distribution-runtime`, `distribution-transport`, `distribution-download`, and `distribution-state` Rust compilation denies warnings and missing public rustdoc; their standalone locked unit suites are invoked by the repository analysis test harness without adding Python production logic.
- Mechanical gates also enforce security document presence, plan `Security Notes`, and basic forbidden-pattern checks.
- Security context is part of architecture, not just implementation detail; docs and plans must record the trust boundary touched by risky changes.
- Supply-chain controls are part of the bootstrap architecture, not a release-afterthought.
Expand Down
7 changes: 7 additions & 0 deletions apps/desktop/distribution-core/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions apps/desktop/distribution-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "bandscope-distribution-core"
version = "0.1.0"
edition = "2021"
description = "Pure Distribution/update anti-replay and rollback decision core for BandScope."
publish = false

[workspace]

[lints.rust]
unsafe_code = "forbid"
warnings = "deny"
missing_docs = "deny"
Loading