Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
81 changes: 81 additions & 0 deletions .github/workflows/developer-onboarding.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
name: Real developer onboarding and consumer gates
on:
push:
paths:
- 'examples/range-client/**'
- 'scripts/developer_walkthrough.py'
- 'tests/test_developer_walkthrough.py'
- '.github/workflows/developer-onboarding.yml'
- 'shadecheck/**'
- 'action.yml'
- 'pyproject.toml'
- 'docs/GETTING_STARTED.md'
workflow_dispatch:
permissions:
contents: read
jobs:
onboarding:
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Build wheel and install into a clean consumer environment
run: |
python -m pip wheel . --wheel-dir "$RUNNER_TEMP/shadecheck-wheels"
python -m venv "$RUNNER_TEMP/shadecheck-consumer"
"$RUNNER_TEMP/shadecheck-consumer/bin/python" -m pip install --no-index --find-links "$RUNNER_TEMP/shadecheck-wheels" shadecheck
- name: Check clean consumer prerequisites
run: '"$RUNNER_TEMP/shadecheck-consumer/bin/python" -m shadecheck.cli doctor --json'
- name: Execute external client baseline and changed behavior on real blocks
run: '"$RUNNER_TEMP/shadecheck-consumer/bin/python" scripts/developer_walkthrough.py --output out/onboarding-ci'
- name: Recompute original evidence without new RPCs
run: '"$RUNNER_TEMP/shadecheck-consumer/bin/python" scripts/developer_walkthrough.py --verify out/onboarding-ci'
- name: Compliant consumer gate must pass
uses: ./
with:
events: out/onboarding-ci/unchanged-run/events.jsonl
config: out/onboarding-ci/policy.json
baseline: out/onboarding-ci/baseline.json
rules: SC-001
output-dir: out/onboarding-action-pass
- name: Changed consumer gate must fail
uses: ./
id: changed
continue-on-error: true
with:
events: out/onboarding-ci/changed-run/events.jsonl
config: out/onboarding-ci/policy.json
baseline: out/onboarding-ci/baseline.json
rules: SC-001
output-dir: out/onboarding-action-fail
- name: Require a real policy failure and regression, not an execution error
env:
ACTUAL_OUTCOME: ${{ steps.changed.outcome }}
ACTUAL_STATUS: ${{ steps.changed.outputs.status }}
ACTUAL_EXIT: ${{ steps.changed.outputs.exit-code }}
run: |
test "$ACTUAL_OUTCOME" = failure
test "$ACTUAL_STATUS" = FAIL
test "$ACTUAL_EXIT" = 1
python - <<'PY'
import json
from pathlib import Path
r=json.loads(Path('out/onboarding-action-fail/report.json').read_text())
assert {f['rule_id'] for f in r['findings']} == {'SC-001','SC-005'}
assert r['baseline_comparison']['regressions'] == 1
PY
- uses: actions/upload-artifact@v4
if: always()
with:
name: real-developer-onboarding
path: |
out/onboarding-ci/
out/onboarding-action-pass/
out/onboarding-action-fail/
retention-days: 30
- name: Stop dedicated regression backend, preserving local data
if: always()
run: docker compose -f integration/compose.yml down
8 changes: 7 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ A transaction can be correctly shielded while application requests still expose
| What you want to do | Where to go |
| --- | --- |
| Explore findings immediately | [Open the public evidence viewer](https://shade-check-nu.vercel.app/) — saved real regtest reports; no setup required |
| Execute fresh tests | [Run locally](#run-the-real-system) with Python and Docker |
| Try the first developer workflow | [Getting started](docs/GETTING_STARTED.md): saved proof or fresh baseline → unchanged → changed-request test |
| Connect your client and enforce CI | [Observer, requirement and consumer integration](docs/CLIENT_INTEGRATION.md) |
| Execute the full five-family suite | [Run locally](#run-the-real-system) with Python and Docker |
| Check what was actually verified | [Acceptance audit](docs/acceptance.md) and [validation record](docs/RELEASE_VALIDATION.md) |
| Inspect an independent client integration | [Current funded Zingo / Zebra / Zaino test](docs/modern-wallet.md) and [original evidence](examples/modern/README.md) |
| Understand the limits | [Threat model](docs/threat-model.md), [rule applicability](docs/rule-applicability.md), and [submission review](docs/JUDGE_REVIEW.md) |
Expand Down Expand Up @@ -63,6 +65,10 @@ Fresh recordings use per-run keyed session identifiers and omit arbitrary broadc

Select requirements that match your actual observer and workflow. A finding is not automatically a newly discovered vulnerability. See [rule applicability and developer actions](docs/rule-applicability.md).

## First developer workflow

Follow [getting started](docs/GETTING_STARTED.md) for Windows and Bash commands, expected outputs and troubleshooting. A separate example client retrieves real completed block ranges through the observer. The walkthrough validates a compliant baseline, a fresh unchanged run and an actual changed request, then asserts the resulting policy and regression exits. The [real onboarding CI](.github/workflows/developer-onboarding.yml) installs a wheel into a clean environment and tests the consumer Action against those traces. [Real onboarding CI](https://github.com/0xaje/ShadeCheck-/actions/runs/40103273814) passed; its [original evidence](examples/range-client/README.md#original-recorded-onboarding-proof) is committed for offline inspection. This is automated clean-environment validation, not a claim of independent user adoption.

## Run the real system

The five-family acceptance suite uses a frozen zcashd/lightwalletd regression backend. It is a controlled test target, not a recommendation for a new production wallet backend. The separate [current Zebra/Zaino wallet integration](docs/modern-wallet.md) validates its own documented coverage.
Expand Down
98 changes: 98 additions & 0 deletions docs/CLIENT_INTEGRATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
# Connect a controlled client and choose a useful CI requirement

First complete the [getting-started walkthrough](GETTING_STARTED.md). The small [range client](../examples/range-client/client.py) is an integration example, not a wallet. Existing wallet integrations require their own supported RPCs, network parameters and reproducible workflow.

## Write the requirement before enabling a gate

Record four things in your integration documentation:

1. Observer: which service can see the requests?
2. Promise: which behavior should that observer not see, or which explicit batching policy should it see?
3. Exercise: which real client workflow provides the required rule coverage?
4. Action: what code/configuration would a developer investigate if it fails?

For this example, the observer serves historical compact blocks; the application promises fixed-size aligned batches for a completed range. A narrower request is a scheduling-policy regression, not proof of wallet ownership or a newly discovered Zcash vulnerability.

A direct broadcasting service inherently receives submitted bytes. SC-002 is appropriate only when that visibility matters to the declared trust model. Hiding a label or removing observation coverage does not establish a privacy improvement.

## Capture actual traffic

Start the dedicated local backend with `python scripts/regtest.py up`. In terminal A:

```bash
python -m shadecheck.cli observe --upstream 127.0.0.1:9067 --plaintext-upstream --port 9068 --output out/my-client/events.jsonl
```

Keep that terminal open. The observer listens on loopback. Plaintext is explicit here for controlled local regtest; use the supported TLS upstream configuration for another approved test environment. No spending key is sent to ShadeCheck.

In terminal B, run your real client against `127.0.0.1:9068`. The example below requests historical heights 80–99, which the initialized local backend must already contain:

```bash
python examples/range-client/client.py --server 127.0.0.1:9068 --start 80 --end 99
```

Wait for the client to complete, then stop terminal A with Ctrl+C. Use a new event path for each run; the recorder refuses to overwrite evidence. The [automated walkthrough](GETTING_STARTED.md) also independently compares every returned block hash with the node.

Create a policy file named `my-policy.json`:

```json
{"schema_version":1,"sync":{"chunk_size":20,"alignment_height":0}}
```

Evaluate only the rule exercised here:

```bash
python -m shadecheck.cli test --events out/my-client/events.jsonl --rules SC-001 --config my-policy.json --policy strict --output out/my-client/report.json
python -m shadecheck.cli report --input out/my-client/report.json --format html --output out/my-client/report.html
```

The complete aligned example should return exit 0. A complete request for heights 83–89 should produce SC-001 and exit 1 under the same policy. Neither result establishes anonymity. Missing coverage, invalid input or execution errors require investigation; strict WARN/errors return 2.

## Baseline and changed behavior

Save the compliant report with its actual evidence:

```bash
python -m shadecheck.cli baseline save --events out/my-client/events.jsonl --input out/my-client/report.json --output my-baseline.json
```

Capture your changed application to a different event file, then:

```bash
python -m shadecheck.cli test --events out/changed/events.jsonl --rules SC-001 --config my-policy.json --baseline my-baseline.json --policy strict --output out/changed/report.json
```

Keep the backend, scenario and requirement comparable. The baseline validates existing evidence; it cannot exempt a known strict failure. A new request pattern does not by itself prove that a particular code change caused it.

## Consumer GitHub Action

Your preceding integration step must start/stop the observer and run the real client. Replace these example paths with the output of that step. The Action evaluates supplied evidence; it does not launch arbitrary wallet code automatically.

This is a job fragment, not a complete workflow file: place `steps` under your own job, and set `permissions` at workflow or job scope. For a complete executable example, use the linked onboarding workflow.

```yaml
permissions:
contents: read
steps:
- uses: actions/checkout@v4
# Run the controlled backend, observer and real client here.
- name: Enforce the declared range policy and baseline
uses: 0xaje/ShadeCheck-@bbbbd166279edcbb92819dddaac6dc2443d6432e
with:
events: out/changed/events.jsonl
config: my-policy.json
baseline: my-baseline.json
rules: SC-001
policy: strict
output-dir: out/privacy-gate
- uses: actions/upload-artifact@v4
if: always()
with:
name: private-test-evidence
path: out/privacy-gate/
retention-days: 7
```

Configure this check as required in the consumer repository if you intend it to block merges. GitHub repository visibility and artifact permissions determine who can read uploaded evidence; the name “private-test-evidence” is not access control. Use throwaway regtest data for public CI, and review [evidence handling](evidence-privacy.md).

The repository's [real onboarding workflow](../.github/workflows/developer-onboarding.yml) contains a complete executable consumer example with both positive and negative gates. Its negative case allows failure only temporarily, then requires exact exit 1 plus SC-001 and SC-005 findings. An arbitrary process error cannot make that workflow pass.
130 changes: 130 additions & 0 deletions docs/GETTING_STARTED.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Start using ShadeCheck

ShadeCheck checks declared, observable Zcash application behavior and produces evidence-backed CI results. The public website displays recorded evidence. Fresh execution happens in your local checkout or GitHub Actions.

Choose a path:

| Goal | Requirements | What you get |
| --- | --- | --- |
| Inspect the current funded-wallet proof | Git, Python 3.11+; package dependencies | Recomputed saved evidence; no Docker, Rust, funds or wallet required |
| Run a small fresh developer workflow | Above plus Docker Linux engine and Compose v2 | Three real client traces, a baseline, HTML/JSON reports and tested CI decisions |
| Test the current independent wallet yourself | Docker, Rust and native build tools | A fresh funded Zingo / Zebra / Zaino test; [separate instructions](modern-wallet.md) |

## 1. Install in a fresh user-owned directory

Use your home directory, not Windows System32. Keep separate virtual environments for Windows and WSL/Linux. These commands clone a new checkout; they do not delete existing evidence or wallet data.

Windows PowerShell:

```powershell
cd $HOME
git clone https://github.com/0xaje/ShadeCheck- ShadeCheck
cd ShadeCheck
py -m venv .venv
.\.venv\Scripts\python.exe -m pip install .
```

Bash/WSL/Linux:

```bash
cd ~
git clone https://github.com/0xaje/ShadeCheck- ShadeCheck
cd ShadeCheck
python3 -m venv .venv
./.venv/bin/python -m pip install .
```

The first-run commands below use the environment's Python explicitly; activation is unnecessary. In the deeper integration guide, `python` means this same environment's interpreter.

## 2. Inspect real recorded wallet evidence first

PowerShell:

```powershell
.\.venv\Scripts\python.exe -m zipfile -e examples/modern/recorded-regtest-20261024.zip out/modern-recorded
.\.venv\Scripts\python.exe scripts/modern_wallet.py --verify out/modern-recorded/20261024T135437-8bcfe43c
```

Bash/WSL:

```bash
./.venv/bin/python -m zipfile -e examples/modern/recorded-regtest-20261024.zip out/modern-recorded
./.venv/bin/python scripts/modern_wallet.py --verify out/modern-recorded/20261024T135437-8bcfe43c
```

Expect `MODERN WALLET ARTIFACTS VERIFIED`. Open that directory's `report.html`. The two HIGH SC-002 findings describe observable broadcasts in explicit upstream local test transport. Verification success means saved evidence recomputed correctly; it does not mean the privacy report passed or that a fresh wallet ran on your computer. [Exact source CI and limits](../examples/modern/README.md).

If you want to inspect the baseline-to-regression decision without Docker, the [original recorded developer walkthrough](../examples/range-client/README.md#original-recorded-onboarding-proof) has a separate downloadable archive and verifier.

## 3. Run the fresh developer walkthrough

Start Docker Desktop with Linux containers, or Docker Engine with Compose v2. Then:

PowerShell:

```powershell
.\.venv\Scripts\python.exe -m shadecheck.cli doctor
.\.venv\Scripts\python.exe scripts/developer_walkthrough.py
```

Bash/WSL:

```bash
./.venv/bin/python -m shadecheck.cli doctor
./.venv/bin/python scripts/developer_walkthrough.py
```

`doctor` must report READY. This checks prerequisites only. The walkthrough starts the dedicated frozen regression backend, checks its regtest network, then runs a separate client process outside the checkout. The initial image build can take several minutes; keep the terminal open. It uses actual locally generated blocks and no public funds. No new transaction or wallet integration is claimed by this range-client example.

The declared requirement is: **for this completed historical range, the block-serving observer must see a 20-block request beginning at a multiple of 20**.

| Actual behavior | Privacy result | Strict CLI exit | Baseline comparison |
| --- | --- | --- | --- |
| Compliant request: 20 aligned blocks | PASS | 0 | Saved as baseline |
| Fresh unchanged request: same 20 blocks | PASS | 0 | PASS, zero regressions |
| Changed request: seven blocks starting three blocks later | FAIL, SC-001 | 1 | FAIL, one SC-005 regression |

Every response is checked against the canonical node. The script exits 0 only after all expected outcomes have been verified, including the deliberately failing request. An execution error returns 2; it is never accepted as the expected policy failure.

At completion, the terminal prints `REAL DEVELOPER WALKTHROUGH VERIFIED` and the exact output directory. Inspect:

- `policy.json`: the requirement selected before the requests.
- `baseline-run/`, `unchanged-run/`, `changed-run/`: actual events, external-client receipts, node proofs and JSON/HTML reports.
- `baseline.json`: portable evidence-backed baseline.
- `changed-run-comparison.html`: the new regression and its current evidence.
- `walkthrough.json`: original artifact inventory and asserted exit codes.

The program chooses a unique output directory by default. `--output PATH` requires a new directory and preserves existing files. It does not stop Docker after a local run; the backend remains available for integration work. Do not run overlapping suites against the same dedicated stack.

To inspect a saved walkthrough later without starting Docker:

```bash
python scripts/developer_walkthrough.py --verify out/developer-walkthrough/YOUR-RUN
```

This checks recorded consistency, not historical authorship or a new consensus execution. Replacing `YOUR-RUN` with the printed directory is required.

## 4. Decide whether this policy belongs in your application

This test is useful when your client deliberately promises fixed historical range batching to this observer. It does not prove wallet history, ownership or anonymity. Fetching 20 blocks rather than seven returns 13 additional blocks in this example; actual bandwidth and timing costs depend on their contents and transport.

Live tip truncation, reorgs and resuming may legitimately require other patterns. Do not copy this strict policy onto every wallet. [Rule applicability](rule-applicability.md) explains exceptions. [Integrate a client](CLIENT_INTEGRATION.md) shows the observer and CI wiring.

For your own implementation, fix the request scheduling that violates the intended requirement, then capture a fresh run. Do not repair evidence, loosen a requirement merely for a green badge, or replace a failing baseline without investigation.

## If setup stops

| Symptom | Next action |
| --- | --- |
| `doctor` is BLOCKED / Docker pipe missing | Start Docker Desktop, select Linux containers, and check `docker version` shows a Server. Rerun doctor. |
| Python virtual environment reports permission denied | Use a fresh checkout under your own home directory and a new user-owned environment. Do not install the project with sudo to bypass ownership. |
| Python cannot import grpc or shadecheck | Run pip install with the same environment's Python used to launch the script. |
| No completed range / backend is not ready | Wait for the initial backend startup to finish; inspect `python scripts/regtest.py check`. Do not substitute saved data for fresh execution. |
| Existing output directory | Use the default unique directory or choose a different `--output` path. |
| WARN or exit 2 | Inspect required coverage and the error. Missing evidence or execution failure is not a passing privacy test. |

On Bash: `docker compose -f integration/compose.yml down` stops this dedicated backend while retaining its volumes. Do not add `-v` to routine shutdown. Windows users can run the same Docker command in PowerShell.

## What this onboarding check establishes

The automated workflow builds an actual wheel, installs it into a fresh virtual environment, runs the example client outside the checkout, validates real node-backed results, then exercises passing and failing consumer Actions. The [first real run](https://github.com/0xaje/ShadeCheck-/actions/runs/40103273814) completed successfully; its [original evidence](../examples/range-client/README.md#original-recorded-onboarding-proof) was downloaded and revalidated. Each future run must still pass CI and the artifact verifier. It does not establish that an unfamiliar person can follow the instructions unaided. Use the [independent reader exercise](ONBOARDING_REVIEW.md) to test that separately.
Loading
Loading