diff --git a/.devcontainer/.env.development b/.devcontainer/.env.development index aa5763d9ee2..8854b79664d 100644 --- a/.devcontainer/.env.development +++ b/.devcontainer/.env.development @@ -381,6 +381,17 @@ B4_PG_DATABASE=b4 B4_BIND=0.0.0.0:50051 B4_URL=http://b4:50051 +# wbraid (packages/wbraid) dev loop. b4.sh, serve.sh and the live-b4 tests read +# these and fall back to the upstream defaults when unset (b4 on 3000, the +# emulator's server on 8080, S3 on localhost:4566). 3000 is the voting portal's +# and 8080 is Hasura's, hence the different ports here; S3 is the opt-in +# `localstack` compose service. +# These can be removed once the wbraid tree is integrated into the parent system. +WBRAID_B4_BIND=127.0.0.1:3005 +WBRAID_B4_URL=http://127.0.0.1:3005 +WBRAID_S3_ENDPOINT_URL=http://localstack:4566 +WBRAID_SERVE_PORT=8085 + # loadero LOADERO_BASE_URL=https://api.loadero.com/v2/projects/13356 LOADERO_API_KEY=a133481e0cf90882554c73bac3e7b2e82a8d79e19c170ed5 diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 4b1582278fc..74e6e22978e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -21,7 +21,9 @@ "rabbitmq:5672", "rabbitmq:15672", "b4:50051", - "simplesamlphp:8083" + "simplesamlphp:8083", + // wbraid's S3 emulator (opt-in profile; packages/wbraid/localstack.sh) + "localstack:4566" ], // Fixes usage of LOCAL_WORKSPACE_FOLDER. See: // https://github.com/microsoft/vscode-remote-release/issues/6844#issuecomment-1252288457 diff --git a/.devcontainer/docker-compose-base.yml b/.devcontainer/docker-compose-base.yml index e5c6f316b30..594c55fe58d 100644 --- a/.devcontainer/docker-compose-base.yml +++ b/.devcontainer/docker-compose-base.yml @@ -165,6 +165,49 @@ services: - KEYCLOAK_ELECTION_EVENT_REALM_CONFIG_S3_KEY=${KEYCLOAK_ELECTION_EVENT_REALM_CONFIG_S3_KEY} entrypoint: /scripts/entrypoint.sh + # S3 emulator for the wbraid dev loop (packages/wbraid): its b4v6 bulletin + # board keeps every message body in S3. Opt-in profile — not started with the + # base stack; packages/wbraid/localstack.sh brings it up by name, which + # auto-enables the profile. + # The image is pinned to the 4.x line: from the 2026 calendar releases on, + # localstack/localstack:latest exits at startup without an auth token. + localstack: + profiles: [ "wbraid" ] + container_name: localstack + image: localstack/localstack:4 + ports: + - "4566:4566" + environment: + - HOSTNAME_EXTERNAL=localhost + - S3_HOSTNAME=localhost:4566 + healthcheck: + test: [ "CMD-SHELL", "curl -sf http://localhost:4566/_localstack/health" ] + interval: 5s + timeout: 10s + retries: 25 + start_period: 5s + + # Creates the wbraid-messages bucket and applies its CORS rules — the twin of + # what localstack.ps1 does inline on Windows. + configure-localstack: + profiles: [ "wbraid" ] + container_name: configure-localstack + image: amazon/aws-cli + volumes: + - "${LOCAL_WORKSPACE_FOLDER:-..}/packages/wbraid/s3-cors.json:/aws/s3-cors.json:ro,z" + depends_on: + localstack: + condition: service_healthy + environment: + - AWS_ACCESS_KEY_ID=test + - AWS_SECRET_ACCESS_KEY=test + - AWS_DEFAULT_REGION=us-east-1 + entrypoint: /bin/sh + command: >- + -c "aws --endpoint-url=http://localstack:4566 s3 mb s3://wbraid-messages 2>/dev/null; + aws --endpoint-url=http://localstack:4566 s3api put-bucket-cors + --bucket wbraid-messages --cors-configuration file:///aws/s3-cors.json" + # hashicorp vault to store secrets # vault: # profiles: ["full", "base"] diff --git a/.github/actions/setup-rust-tests/action.yml b/.github/actions/setup-rust-tests/action.yml index e611537a168..377b1bdc695 100644 --- a/.github/actions/setup-rust-tests/action.yml +++ b/.github/actions/setup-rust-tests/action.yml @@ -15,6 +15,14 @@ inputs: cargo-lock-path: description: Cargo lockfile used to invalidate the package build cache required: true + components: + description: Toolchain components to install (comma-separated) + required: false + default: rustfmt + targets: + description: Extra compilation targets to install (comma-separated) + required: false + default: x86_64-unknown-linux-musl runs: using: composite @@ -23,8 +31,8 @@ runs: uses: dtolnay/rust-toolchain@stable with: toolchain: 1.96.0 - components: rustfmt - targets: x86_64-unknown-linux-musl + components: ${{ inputs.components }} + targets: ${{ inputs.targets }} - name: Cache Cargo registry uses: actions/cache@v4 diff --git a/.github/workflows/wbraid.yml b/.github/workflows/wbraid.yml new file mode 100644 index 00000000000..230ab2c4182 --- /dev/null +++ b/.github/workflows/wbraid.yml @@ -0,0 +1,107 @@ +# SPDX-FileCopyrightText: 2026 Sequent Tech Inc +# +# SPDX-License-Identifier: AGPL-3.0-only + +name: wbraid + +# packages/wbraid is its own Cargo workspace (see packages/wbraid/PROVENANCE.md), +# so it gets its own workflow, scoped to changes under that subtree. +on: + pull_request: + paths: + - 'packages/wbraid/**' + - '.github/workflows/wbraid.yml' + - '.github/actions/setup-rust-tests/**' + push: + branches: [ 'main', 'release/[0-9]+.[0-9]+' ] + paths: + - 'packages/wbraid/**' + - '.github/workflows/wbraid.yml' + - '.github/actions/setup-rust-tests/**' + +defaults: + run: + working-directory: packages/wbraid + +jobs: + lint: + name: Format and lint + runs-on: ubuntu-24.04 + timeout-minutes: 30 + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: ./.github/actions/setup-rust-tests + with: + cargo-build-name: wbraid-lint + cargo-build-path: packages/wbraid/target + cargo-lock-path: packages/wbraid/Cargo.lock + components: rustfmt, clippy + + - name: Check formatting + run: cargo fmt -- --check + + # vsc is a vendored fork with its own strict lint levels; its test modules + # and the shuffle_scaling example fail those upstream levels (identically + # on nightly, see PROVENANCE.md), and under -D warnings its warn-level + # lints (indexing_slicing) would fail too. --no-deps keeps -D warnings + # from leaking into vsc through the workspace wrapper; the second + # invocation lints vsc's lib at exactly the levels upstream chose. + - name: Clippy (workspace except vsc, all targets) + run: cargo clippy --workspace --exclude vsc --all-targets --no-deps -- -D warnings + + - name: Clippy (vsc lib, upstream lint levels) + run: cargo clippy -p vsc --no-deps + + test: + name: Run tests + runs-on: ubuntu-24.04 + timeout-minutes: 45 + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: ./.github/actions/setup-rust-tests + with: + cargo-build-name: wbraid-test + cargo-build-path: packages/wbraid/target + cargo-lock-path: packages/wbraid/Cargo.lock + + # The live-b4 protocol tests (test_protocol_http*) and the Verificatum + # interop tests are #[ignore]d: they need a running b4 + LocalStack or a + # JVM with the Verificatum jars. The live-b4 ones stay ignored here until + # a follow-up gives this job b4 and LocalStack service containers. + - name: Run tests + run: cargo test --release + env: + RUST_BACKTRACE: 'full' + + build-wasm-core: + name: Build wasm-core + runs-on: ubuntu-24.04 + timeout-minutes: 30 + steps: + - name: Check out code + uses: actions/checkout@v4 + + - name: Set up Rust + uses: ./.github/actions/setup-rust-tests + with: + cargo-build-name: wbraid-wasm + cargo-build-path: packages/wbraid/target + cargo-lock-path: packages/wbraid/Cargo.lock + targets: wasm32-unknown-unknown + + # Run from the workspace root so crates/braid/.cargo/config.toml (atomics + # + build-std, which need RUSTC_BOOTSTRAP on stable) does not apply; the + # wasm-core feature needs neither, and the build stops before bindings, + # so no wasm-bindgen-cli is required. The full atomics `wasm` feature + # build stays a dev-loop concern (build-wasm.sh / build-wasm.ps1). + - name: Build braid wasm-core + run: >- + cargo build -p braid --lib --release + --target wasm32-unknown-unknown + --no-default-features --features wasm-core diff --git a/.vscode/tasks.shared.json b/.vscode/tasks.shared.json index 68b417b7151..ab4761056d8 100644 --- a/.vscode/tasks.shared.json +++ b/.vscode/tasks.shared.json @@ -2,1388 +2,1613 @@ // // SPDX-License-Identifier: AGPL-3.0-only { - "version": "2.0.0", - "tasks": [ - { - "label": "report.locs", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./scripts/loc.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": false, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "generate.dependency.report", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./scripts/tasks/dependencies/generate-dependency-report.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": false, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "security.audit.dependencies", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./scripts/tasks/security/audit-dependencies.sh", - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": false, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "check.reuse", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "reuse lint", - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.admin-portal", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd packages && yarn start:admin-portal" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.storybook.ui-essentials", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd packages && yarn storybook:ui-essentials" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.results-portal", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd packages && yarn start:results-portal", - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.docusaurus", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd docs/docusaurus && yarn && yarn start" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.build.docusaurus", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd docs/docusaurus && yarn && yarn build" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "run.claude", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "claude --dangerously-skip-permissions" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "run.spectaql", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd docs/api/graphql && yarn && yarn run generate-full-docs && python -m http.server -d docs" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.build.admin-portal", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd packages && yarn && yarn build:ui-core && yarn build:ui-essentials && yarn start:admin-portal" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.build.results-portal", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd packages && yarn && yarn build:ui-core && yarn build:ui-essentials && yarn build:results-portal && yarn start:results-portal", - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.voting-portal", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd packages && yarn start:voting-portal" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "start.ballot-verifier", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd packages && yarn start:ballot-verifier" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.hasura", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "graphql-engine" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.keycloak", - "command": "bash", - "args": [ - "-c", - "docker compose stop keycloak keycloak-nginx; docker compose build keycloak keycloak-nginx && docker compose up -d --no-deps keycloak && docker compose up -d --no-deps keycloak-nginx && docker compose logs -f --tail 100 keycloak keycloak-nginx" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, { - "label": "rebuild.janitor", - "command": "bash", - "args": [ - "-c", - "docker compose stop janitor; docker compose build janitor && docker compose up -d --no-deps janitor" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.simplesamlphp", - "command": "bash", - "args": [ - "-c", - "docker compose stop simplesamlphp; docker compose build simplesamlphp && docker compose up -d --no-deps simplesamlphp && docker compose logs -f --tail 100 simplesamlphp" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.hasura", - "command": "bash", - "args": [ - "-c", - "docker compose stop graphql-engine; docker compose up -d --no-deps graphql-engine && docker compose logs -f --tail 100 graphql-engine" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.harvest", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "harvest" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.harvest", - "command": "bash", - "args": [ - "-c", - "docker compose stop harvest; docker compose up -d --no-deps harvest && docker compose logs -f --tail 100 harvest" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.b4", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "b4", - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.b4", - "command": "bash", - "args": [ - "-c", - "docker compose stop b4; docker compose up -d --no-deps b4 && docker compose logs -f --tail 100 b4", - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.keycloak", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "keycloak" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.keycloak-nginx", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "keycloak-nginx" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.keycloak-nginx", - "command": "bash", - "args": [ - "-c", - "docker compose stop keycloak-nginx; docker compose build keycloak-nginx && docker compose up -d --no-deps keycloak-nginx && docker compose logs -f --tail 100 keycloak-nginx" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.simplesamlphp", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "simplesamlphp" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.beat", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "beat" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.beat", - "command": "bash", - "args": [ - "-c", - "docker compose stop beat; docker compose up -d --no-deps beat && docker compose logs -f --tail 100 beat" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.windmill", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "windmill" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.windmill", - "command": "bash", - "args": [ - "-c", - "docker compose stop windmill; docker compose up -d --no-deps windmill && docker compose logs -f --tail 100 windmill" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.trustees", - "command": "bash", - "args": [ - "-c", - "docker compose logs -f --tail 100 trustee1 trustee2" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.minio", - "command": "bash", - "args": [ - "-c", - "docker compose stop minio configure-minio && docker compose up --no-deps --wait --wait-timeout 120 minio && docker compose up --build --no-deps configure-minio && docker compose logs -f --tail 100 configure-minio minio" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.minio", - "command": "bash", - "args": [ - "-c", - "docker compose logs -f --tail 100 minio" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.reset.minio", - "command": "bash", - "args": [ - "-c", - "docker compose stop minio configure-minio && docker compose up --no-deps --wait --wait-timeout 120 minio && docker compose up --build --no-deps configure-minio && docker compose logs -f minio configure-minio", - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] - }, - { - "label": "logs.restart.trustees", - "command": "bash", - "args": [ - "-c", - "docker compose stop trustee1 trustee2; docker compose up -d --no-deps trustee1 trustee2 && docker compose logs -f --tail 100 trustee1 trustee2" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "version": "2.0.0", + "tasks": [ + { + "label": "report.locs", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./scripts/loc.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": false, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "generate.dependency.report", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./scripts/tasks/dependencies/generate-dependency-report.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "security.audit.dependencies", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./scripts/tasks/security/audit-dependencies.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "check.reuse", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "reuse lint" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.admin-portal", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages && yarn start:admin-portal" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.storybook.ui-essentials", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages && yarn storybook:ui-essentials" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.results-portal", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages && yarn start:results-portal" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.docusaurus", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd docs/docusaurus && yarn && yarn start" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.build.docusaurus", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd docs/docusaurus && yarn && yarn build" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "run.claude", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "claude --dangerously-skip-permissions" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "run.spectaql", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd docs/api/graphql && yarn && yarn run generate-full-docs && python -m http.server -d docs" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.build.admin-portal", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages && yarn && yarn build:ui-core && yarn build:ui-essentials && yarn start:admin-portal" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.build.results-portal", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages && yarn && yarn build:ui-core && yarn build:ui-essentials && yarn build:results-portal && yarn start:results-portal" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.voting-portal", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages && yarn start:voting-portal" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.ballot-verifier", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages && yarn start:ballot-verifier" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.hasura", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "graphql-engine" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.keycloak", + "command": "bash", + "args": [ + "-c", + "docker compose stop keycloak keycloak-nginx; docker compose build keycloak keycloak-nginx && docker compose up -d --no-deps keycloak && docker compose up -d --no-deps keycloak-nginx && docker compose logs -f --tail 100 keycloak keycloak-nginx" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "update.env", - "command": "bash", - "args": [ - "./.devcontainer/scripts/initialize-command.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "rebuild.janitor", + "command": "bash", + "args": [ + "-c", + "docker compose stop janitor; docker compose build janitor && docker compose up -d --no-deps janitor" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "init.cli", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "cd /workspaces/step/packages/step-cli && cargo build --release && /workspaces/step/.devcontainer/scripts/config-cli.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.simplesamlphp", + "command": "bash", + "args": [ + "-c", + "docker compose stop simplesamlphp; docker compose build simplesamlphp && docker compose up -d --no-deps simplesamlphp && docker compose logs -f --tail 100 simplesamlphp" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "update.vscode.settings", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./.devcontainer/scripts/fix-vscode-settings-nix.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.hasura", + "command": "bash", + "args": [ + "-c", + "docker compose stop graphql-engine; docker compose up -d --no-deps graphql-engine && docker compose logs -f --tail 100 graphql-engine" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "update.graphql", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./.devcontainer/scripts/update-graphql.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.harvest", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "harvest" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.harvest", + "command": "bash", + "args": [ + "-c", + "docker compose stop harvest; docker compose up -d --no-deps harvest && docker compose logs -f --tail 100 harvest" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "format.code", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./.devcontainer/scripts/format-code.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.b4", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "b4" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.b4", + "command": "bash", + "args": [ + "-c", + "docker compose stop b4; docker compose up -d --no-deps b4 && docker compose logs -f --tail 100 b4" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "build.sequent-core", - "type": "shell", - "command": "bash", - "args": [ - "-l", - "-c", - "cd /workspaces/step/packages/sequent-core && nix develop --command ../../.devcontainer/scripts/build-sequent-core.sh" - ], - "options": { - "cwd": "${workspaceFolder}" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": false, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.keycloak", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "keycloak" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.keycloak-nginx", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "keycloak-nginx" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.keycloak-nginx", + "command": "bash", + "args": [ + "-c", + "docker compose stop keycloak-nginx; docker compose build keycloak-nginx && docker compose up -d --no-deps keycloak-nginx && docker compose logs -f --tail 100 keycloak-nginx" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "rebuild.sequent-core.full", - "type": "shell", - "command": "bash", - "args": [ - "-l", - "-c", - "cd /workspaces/step/packages/sequent-core && nix develop --command ../../.devcontainer/scripts/rebuild-sequent-core-full.sh && direnv exec /workspaces/step bash -c \"cd /workspaces/step/packages && yarn && yarn build:ui-core && yarn build:ui-essentials\"" - ], - "options": { - "cwd": "${workspaceFolder}" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": true - }, - "isBackground": false, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.simplesamlphp", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "simplesamlphp" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.beat", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "beat" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.beat", + "command": "bash", + "args": [ + "-c", + "docker compose stop beat; docker compose up -d --no-deps beat && docker compose logs -f --tail 100 beat" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "rebuild.braid-wasm.full", - "type": "shell", - "command": "bash", - "args": [ - "-l", - "-c", - "/workspaces/step/packages/braid/scripts/build-wasm.sh && direnv exec /workspaces/step bash -c \"cd /workspaces/step/packages && yarn\"" - ], - "options": { - "cwd": "${workspaceFolder}" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": true - }, - "isBackground": false, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.windmill", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "windmill" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.windmill", + "command": "bash", + "args": [ + "-c", + "docker compose stop windmill; docker compose up -d --no-deps windmill && docker compose logs -f --tail 100 windmill" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "logs.orare", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "orare" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.trustees", + "command": "bash", + "args": [ + "-c", + "docker compose logs -f --tail 100 trustee1 trustee2" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "logs.restart.orare", - "command": "bash", - "args": [ - "-c", - "docker compose stop openwhisk orare; docker compose up -d --no-deps openwhisk && sleep 10 && docker compose up -d --no-deps orare && docker compose logs -f --tail 100 openwhisk orare" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base", - "PDF_TRANSPORT_NAME": "orare-openwhisk" - }, - "cwd": "${workspaceFolder}/.devcontainer" - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.minio", + "command": "bash", + "args": [ + "-c", + "docker compose stop minio configure-minio && docker compose up --no-deps --wait --wait-timeout 120 minio && docker compose up --build --no-deps configure-minio && docker compose logs -f --tail 100 configure-minio minio" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "logs.openwhisk", - "command": "docker", - "args": [ - "compose", - "logs", - "-f", - "--tail", - "200", - "openwhisk" - ], - "options": { - "env": { - "COMPOSE_PROJECT_NAME": "step_devcontainer", - "COMPOSE_PROFILES": "base" - } - }, - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.minio", + "command": "bash", + "args": [ + "-c", + "docker compose logs -f --tail 100 minio" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "free.space", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./.devcontainer/scripts/free-space.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.reset.minio", + "command": "bash", + "args": [ + "-c", + "docker compose stop minio configure-minio && docker compose up --no-deps --wait --wait-timeout 120 minio && docker compose up --build --no-deps configure-minio && docker compose logs -f minio configure-minio" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "fix.docker", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "rm -rf /home/vscode/.docker/" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": false, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.trustees", + "command": "bash", + "args": [ + "-c", + "docker compose stop trustee1 trustee2; docker compose up -d --no-deps trustee1 trustee2 && docker compose logs -f --tail 100 trustee1 trustee2" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" }, - { - "label": "update.license.headers", - "command": "devenv", - "args": [ - "shell", - "python3", - "--", - "./scripts/update_license_headers.py", - ".", - "--include-excluded" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "update.env", + "command": "bash", + "args": [ + "./.devcontainer/scripts/initialize-command.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "init.cli", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd /workspaces/step/packages/step-cli && cargo build --release && /workspaces/step/.devcontainer/scripts/config-cli.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "update.vscode.settings", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./.devcontainer/scripts/fix-vscode-settings-nix.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "update.graphql", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./.devcontainer/scripts/update-graphql.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "format.code", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./.devcontainer/scripts/format-code.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "build.sequent-core", + "type": "shell", + "command": "bash", + "args": [ + "-l", + "-c", + "cd /workspaces/step/packages/sequent-core && nix develop --command ../../.devcontainer/scripts/build-sequent-core.sh" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "rebuild.sequent-core.full", + "type": "shell", + "command": "bash", + "args": [ + "-l", + "-c", + "cd /workspaces/step/packages/sequent-core && nix develop --command ../../.devcontainer/scripts/rebuild-sequent-core-full.sh && direnv exec /workspaces/step bash -c \"cd /workspaces/step/packages && yarn && yarn build:ui-core && yarn build:ui-essentials\"" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": true + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "rebuild.braid-wasm.full", + "type": "shell", + "command": "bash", + "args": [ + "-l", + "-c", + "/workspaces/step/packages/braid/scripts/build-wasm.sh && direnv exec /workspaces/step bash -c \"cd /workspaces/step/packages && yarn\"" + ], + "options": { + "cwd": "${workspaceFolder}" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": true + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.orare", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "orare" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" + } + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.restart.orare", + "command": "bash", + "args": [ + "-c", + "docker compose stop openwhisk orare; docker compose up -d --no-deps openwhisk && sleep 10 && docker compose up -d --no-deps orare && docker compose logs -f --tail 100 openwhisk orare" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base", + "PDF_TRANSPORT_NAME": "orare-openwhisk" }, - { - "label": "upload.plugins", - "command": "devenv", - "args": [ - "shell", - "bash", - "--", - "-c", - "./.devcontainer/scripts/upload_plugins_to_s3.sh" - ], - "presentation": { - "echo": true, - "reveal": "always", - "focus": false, - "panel": "dedicated", - "showReuseMessage": true, - "clear": false - }, - "isBackground": true, - "runOptions": { - "runOn": "default" - }, - "problemMatcher": [] + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.openwhisk", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "openwhisk" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "base" } - ] + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "free.space", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./.devcontainer/scripts/free-space.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "fix.docker", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "rm -rf /home/vscode/.docker/" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": false, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "update.license.headers", + "command": "devenv", + "args": [ + "shell", + "python3", + "--", + "./scripts/update_license_headers.py", + ".", + "--include-excluded" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "upload.plugins", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "./.devcontainer/scripts/upload_plugins_to_s3.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "build.wbraid-wasm", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && ./build-wasm.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "test.wbraid-wasm", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && ./test-wasm.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "test.wbraid", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && cargo test --release" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "check.wbraid", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && unset RUSTFLAGS && cargo fmt -- --check && cargo clippy --workspace --exclude vsc --all-targets --no-deps -- -D warnings && cargo clippy -p vsc --no-deps" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.wbraid-localstack", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && ./localstack.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.wbraid-b4", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && ./b4.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "reset.wbraid-b4", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && ./b4.sh --reset --no-run" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": false, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "start.wbraid-serve", + "command": "devenv", + "args": [ + "shell", + "bash", + "--", + "-c", + "cd packages/wbraid && ./serve.sh" + ], + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + }, + { + "label": "logs.localstack", + "command": "docker", + "args": [ + "compose", + "logs", + "-f", + "--tail", + "200", + "localstack" + ], + "options": { + "env": { + "COMPOSE_PROJECT_NAME": "step_devcontainer", + "COMPOSE_PROFILES": "wbraid" + }, + "cwd": "${workspaceFolder}/.devcontainer" + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": false, + "panel": "dedicated", + "showReuseMessage": true, + "clear": false + }, + "isBackground": true, + "runOptions": { + "runOn": "default" + }, + "problemMatcher": [] + } + ] } diff --git a/CLAUDE.md b/CLAUDE.md index d7475ff85b5..07c19d95a0d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -128,7 +128,7 @@ reuse lint # Every file must have SPDX headers // SPDX-License-Identifier: AGPL-3.0-only ``` - **Vendored Cargo dependencies**: `packages/vendor/` — Cargo.toml uses `[source.vendored-sources]` -- **Pinned crate**: `wasm-bindgen` 0.2.104 — do not change +- **Pinned crate**: `wasm-bindgen` 0.2.123 (`=0.2.123` in strand, braid, sequent-core and `packages/wbraid`) — the CLI pins in `devenv.nix` and the three `flake.nix` files must move with it - **Forked crate**: `celery` uses a custom fork (Findeton/rusty-celery) - **Hasura changes must go through** `hasura console` (not the web UI directly) for migrations to be tracked - **Rust toolchain**: 1.96.0 stable, WASM targets: `wasm32-unknown-unknown` diff --git a/devenv.lock b/devenv.lock index 4b3ea84a25d..714f70c5ade 100644 --- a/devenv.lock +++ b/devenv.lock @@ -107,12 +107,28 @@ "type": "github" } }, + "nixpkgs-crates": { + "locked": { + "lastModified": 1788297115, + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "a3116115851d68b8952a2a4221cc25a84e56b532", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-26.05", + "repo": "nixpkgs", + "type": "github" + } + }, "root": { "inputs": { "devenv": "devenv", "fenix": "fenix", "git-hooks": "git-hooks", "nixpkgs": "nixpkgs", + "nixpkgs-crates": "nixpkgs-crates", "pre-commit-hooks": [ "git-hooks" ], diff --git a/devenv.nix b/devenv.nix index 142c2e50615..2d15c9fbf5d 100644 --- a/devenv.nix +++ b/devenv.nix @@ -1,4 +1,4 @@ -{ pkgs, ... }: +{ pkgs, inputs, ... }: # Check docs/docusaurus/docs/07-developers/11-updates/updating-rust-version.md on how to update rust version. let @@ -7,6 +7,10 @@ let sha256 = "138jwq564qji7dc5yav2j2c1c1mr65smqqk00mni9lvqhx0n45w4"; }); + pkgsCrates = import inputs.nixpkgs-crates { + inherit (pkgs.stdenv.hostPlatform) system; + }; + pkgs' = pkgs.extend rustOverlay; rustStable = pkgs'.rust-bin.stable."1.96.0".default.override { @@ -14,20 +18,27 @@ let extensions = [ "rust-src" "rust-analyzer-preview" ]; }; - # Pin wasm-bindgen-cli to match the wasm-bindgen crate version in Cargo.toml (=0.2.104) - # The CLI and crate versions must match exactly - wasm-bindgen-cli-pinned = pkgs.rustPlatform.buildRustPackage rec { + # wasm-bindgen has no semver guarantee, so the CLI must match the crate + # version exactly (=0.2.123). Not in nixpkgs, so this is a source build. + # Built entirely against pkgsCrates (nixos-26.05): the crate vendorer in + # our main pin sends a default python-requests User-Agent, which crates.io + # answers with HTTP 403. The rustc that builds the CLI is 26.05's and need + # not match our 1.96.0 — only the CLI *version* must match the crate. + wasm-bindgen-cli-pinned = pkgsCrates.rustPlatform.buildRustPackage rec { pname = "wasm-bindgen-cli"; - version = "0.2.104"; + # Pinned to the wasm-bindgen crate version both Cargo workspaces use + # (packages/Cargo.toml and packages/wbraid/Cargo.toml: =0.2.123). + version = "0.2.123"; + cargoHash = "sha256-d7x6gtx5OqEE4MyT6yjYn/qtgjx7GroTpXJewnBV2dU="; src = builtins.fetchTarball { - url = "https://crates.io/api/v1/crates/${pname}/${version}/download"; - sha256 = "00bv402z5n47f7l582xmanaxraacwg2pcm6rvlcify1bn9mvwign"; + url = "https://static.crates.io/crates/wasm-bindgen-cli/wasm-bindgen-cli-${version}.crate"; + sha256 = "12xdns7cvnz0j26i9kryxggylsslkqs5l2b6lppfkv1bic8q0rya"; }; - cargoHash = "sha256-V0AV5jkve37a5B/UvJ9B3kwOW72vWblST8Zxs8oDctE="; - nativeBuildInputs = [ pkgs.pkg-config ]; - buildInputs = [ pkgs.openssl ] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.curl ]; + nativeBuildInputs = [ pkgsCrates.pkg-config ]; + buildInputs = [ pkgsCrates.openssl ] + ++ pkgsCrates.lib.optionals pkgsCrates.stdenv.hostPlatform.isDarwin [ pkgsCrates.curl ]; doCheck = false; + }; in @@ -116,7 +127,7 @@ in yq minio-client - + # AI. Note, requires allowUnfree: true in devenv.yaml claude-code diff --git a/devenv.yaml b/devenv.yaml index 51217d2c3aa..4287ae87612 100644 --- a/devenv.yaml +++ b/devenv.yaml @@ -13,6 +13,8 @@ inputs: follows: nixpkgs nixpkgs: url: github:NixOS/nixpkgs/nixpkgs-unstable + nixpkgs-crates: + url: github:NixOS/nixpkgs/nixos-26.05 fenix: url: github:nix-community/fenix inputs: diff --git a/packages/Cargo.lock b/packages/Cargo.lock index e922864aace..f4ee2dad858 100644 --- a/packages/Cargo.lock +++ b/packages/Cargo.lock @@ -5445,11 +5445,12 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.81" +version = "0.3.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305" +checksum = "f2025f20d7a4fa7785846e7b63d10a76d3f1cee98ee5cb79ea59703f95e42162" dependencies = [ - "once_cell", + "cfg-if", + "futures-util", "wasm-bindgen", ] @@ -6146,9 +6147,9 @@ dependencies = [ [[package]] name = "minicov" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27fe9f1cc3c22e1687f9446c2083c4c5fc7f0bcf1c7a86bdbded14985895b4b" +checksum = "c3aa3aa12b448ac225b3102217d1ac5cc717908f02722926524b0599c933c7a0" dependencies = [ "cc", "walkdir", @@ -6491,6 +6492,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -11192,9 +11194,9 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.104" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d" +checksum = "a254a4b10c19a76f09a27640e7ffbf9bc30bf67e16a3bf28aaefa4920fe81563" dependencies = [ "cfg-if", "once_cell", @@ -11205,38 +11207,21 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.110", - "wasm-bindgen-shared", -] - [[package]] name = "wasm-bindgen-futures" -version = "0.4.54" +version = "0.4.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e038d41e478cc73bae0ff9b36c60cff1c98b8f38f8d7e8061e79ee63608ac5c" +checksum = "54568702fabf5d4849ce2b90fadfa64168a097eaf4b351ce9df8b687a0086aaf" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.104" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119" +checksum = "24a40fc75b0ec6f3746ceb10d36f53a93dcd68a93b11b6445983945d79eba0dc" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -11244,14 +11229,14 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.104" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7" +checksum = "908f34bd9b9ce3d4caf07b72dfab63d61504d156856c6bd3cd87fa350cf3985b" dependencies = [ + "bumpalo", "proc-macro2", "quote", "syn 2.0.110", - "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -11269,37 +11254,52 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.104" +version = "0.2.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1" +checksum = "7acbf7616c27b194bbb550bf77ed0c2c3e5b7fd1260a93082b95fb7f47959b92" dependencies = [ "unicode-ident", ] [[package]] name = "wasm-bindgen-test" -version = "0.3.54" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e381134e148c1062f965a42ed1f5ee933eef2927c3f70d1812158f711d39865" +checksum = "e28a0782b173cf2e98f62aacb487c5c021b7c5925df46098675f28e1fa85e159" dependencies = [ + "async-trait", + "cast", "js-sys", + "libm", "minicov", + "nu-ansi-term", + "num-traits", + "oorandom", + "serde", + "serde_json", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", + "wasm-bindgen-test-shared", ] [[package]] name = "wasm-bindgen-test-macro" -version = "0.3.54" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b673bca3298fe582aeef8352330ecbad91849f85090805582400850f8270a2e8" +checksum = "ee997551ce1ad5adda03f7ce37ec34b4140fe9f547fd07b46d55901d1ba1a06b" dependencies = [ "proc-macro2", "quote", "syn 2.0.110", ] +[[package]] +name = "wasm-bindgen-test-shared" +version = "0.2.123" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae0f005eb61f765eff31a79ef71df7e21819731268a868df41192c1e41d6d3e5" + [[package]] name = "wasm-compose" version = "0.243.0" @@ -11739,9 +11739,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.81" +version = "0.3.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120" +checksum = "6e0871acf327f283dc6da28a1696cdc64fb355ba9f935d052021fa77f35cce69" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/packages/admin-portal/rust/braid-wasm-0.1.0.tgz b/packages/admin-portal/rust/braid-wasm-0.1.0.tgz index b0e76f61ce6..395ac5ae3c0 100644 Binary files a/packages/admin-portal/rust/braid-wasm-0.1.0.tgz and b/packages/admin-portal/rust/braid-wasm-0.1.0.tgz differ diff --git a/packages/admin-portal/rust/sequent-core-0.1.0.tgz b/packages/admin-portal/rust/sequent-core-0.1.0.tgz index 1df27efa16f..e0400358016 100644 Binary files a/packages/admin-portal/rust/sequent-core-0.1.0.tgz and b/packages/admin-portal/rust/sequent-core-0.1.0.tgz differ diff --git a/packages/ballot-verifier/rust/sequent-core-0.1.0.tgz b/packages/ballot-verifier/rust/sequent-core-0.1.0.tgz index 1df27efa16f..e0400358016 100644 Binary files a/packages/ballot-verifier/rust/sequent-core-0.1.0.tgz and b/packages/ballot-verifier/rust/sequent-core-0.1.0.tgz differ diff --git a/packages/braid/Cargo.toml b/packages/braid/Cargo.toml index f73d35c976a..0cb9f93cb5d 100644 --- a/packages/braid/Cargo.toml +++ b/packages/braid/Cargo.toml @@ -32,7 +32,7 @@ aws-sdk-s3 = { version = "1.52", optional = true } chrono = { version = "0.4", optional = true } # WASM-only dependencies -wasm-bindgen = { version = "=0.2.104", optional = true } +wasm-bindgen = { version = "=0.2.123", optional = true } wasm-bindgen-futures = { version = "0.4", optional = true } wasm-bindgen-rayon = { version = "1.3", features = ["no-bundler"], optional = true } js-sys = { version = "0.3", optional = true } diff --git a/packages/braid/flake.lock b/packages/braid/flake.lock index bb6cadca0ac..85f9781dcce 100644 --- a/packages/braid/flake.lock +++ b/packages/braid/flake.lock @@ -50,6 +50,20 @@ "type": "github" } }, + "nixpkgs-crates": { + "locked": { + "lastModified": 1788405554, + "narHash": "sha256-z3ACU3NTAstjK+JNjW0zmIH2Q0GYo2pgGfJddesv7Xo=", + "rev": "a5cc6f2c37bf518436dc8d1c288ccd0c43c2f4c4", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.8954.a5cc6f2c37bf/nixexprs.tar.xz" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-26.05", + "type": "indirect" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1744536153, @@ -71,6 +85,7 @@ "flake-compat": "flake-compat", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", + "nixpkgs-crates": "nixpkgs-crates", "rust-overlay": "rust-overlay" } }, diff --git a/packages/braid/flake.nix b/packages/braid/flake.nix index 44dfce6c32e..5616dda2650 100644 --- a/packages/braid/flake.nix +++ b/packages/braid/flake.nix @@ -8,6 +8,7 @@ # input inputs.rust-overlay.url = "github:oxalica/rust-overlay"; inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-25.05"; + inputs.nixpkgs-crates.url = "nixpkgs/nixos-26.05"; inputs.flake-utils.url = "github:numtide/flake-utils"; inputs.flake-compat = { url = "github:edolstra/flake-compat"; @@ -15,7 +16,7 @@ }; # output function of this flake - outputs = { self, nixpkgs, flake-utils, rust-overlay, flake-compat }: + outputs = { self, nixpkgs, nixpkgs-crates, flake-utils, rust-overlay, flake-compat }: flake-utils.lib.eachDefaultSystem ( system: let @@ -24,26 +25,37 @@ pkgs = import nixpkgs { inherit system overlays; }; - + pkgsCrates = import nixpkgs-crates { + inherit system; + }; + rust-system = pkgs.rust-bin.stable."1.96.0".default.override { targets = [ "wasm32-unknown-unknown" ]; extensions = [ "rust-src" ]; }; - # Pin wasm-bindgen-cli to match the wasm-bindgen crate version in Cargo.toml (=0.2.104) - # The CLI and crate versions must match exactly - wasm-bindgen-cli-pinned = pkgs.rustPlatform.buildRustPackage rec { + + # wasm-bindgen has no semver guarantee, so the CLI must match the crate + # version exactly (=0.2.123). Not in nixpkgs, so this is a source build. + # Built entirely against pkgsCrates (nixos-26.05): the crate vendorer in + # our main pin sends a default python-requests User-Agent, which crates.io + # answers with HTTP 403. The rustc that builds the CLI is 26.05's and need + # not match our 1.96.0 — only the CLI *version* must match the crate. + wasm-bindgen-cli-pinned = pkgsCrates.rustPlatform.buildRustPackage rec { pname = "wasm-bindgen-cli"; - version = "0.2.104"; + # Pinned to the wasm-bindgen crate version both Cargo workspaces use + # (packages/Cargo.toml and packages/wbraid/Cargo.toml: =0.2.123). + version = "0.2.123"; + cargoHash = "sha256-d7x6gtx5OqEE4MyT6yjYn/qtgjx7GroTpXJewnBV2dU="; src = builtins.fetchTarball { - url = "https://crates.io/api/v1/crates/${pname}/${version}/download"; - sha256 = "00bv402z5n47f7l582xmanaxraacwg2pcm6rvlcify1bn9mvwign"; + url = "https://static.crates.io/crates/${pname}/${pname}-${version}.crate"; + sha256 = "12xdns7cvnz0j26i9kryxggylsslkqs5l2b6lppfkv1bic8q0rya"; }; - cargoHash = "sha256-V0AV5jkve37a5B/UvJ9B3kwOW72vWblST8Zxs8oDctE="; - nativeBuildInputs = [ pkgs.pkg-config ]; - buildInputs = [ pkgs.openssl ] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.curl ]; + nativeBuildInputs = [ pkgsCrates.pkg-config ]; + buildInputs = [ pkgsCrates.openssl ] + ++ pkgsCrates.lib.optionals pkgsCrates.stdenv.hostPlatform.isDarwin [ pkgsCrates.curl ]; doCheck = false; }; + # see https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/rust.section.md#importing-a-cargolock-file-importing-a-cargolock-file cargoPatches = { cargoLock = let diff --git a/packages/sequent-core/Cargo.toml b/packages/sequent-core/Cargo.toml index a332ad8810d..1cb2029aa13 100644 --- a/packages/sequent-core/Cargo.toml +++ b/packages/sequent-core/Cargo.toml @@ -29,7 +29,7 @@ borsh = { version = "1.5", features = ["derive"] } # wasm # Note: Using specific version of wasm-bindgen to match Nix version -wasm-bindgen = {version = "=0.2.104", features = ['serde-serialize'], optional = true} +wasm-bindgen = {version = "=0.2.123", features = ['serde-serialize'], optional = true} serde-wasm-bindgen = { version = "0.6", optional = true } web-sys = { version = "0.3", features = ['Performance', 'console'], optional = true} cfg-if = "1.0" diff --git a/packages/sequent-core/flake.lock b/packages/sequent-core/flake.lock index 8c0e76e1ac0..e003a82eb23 100644 --- a/packages/sequent-core/flake.lock +++ b/packages/sequent-core/flake.lock @@ -234,6 +234,20 @@ "type": "github" } }, + "nixpkgs-crates": { + "locked": { + "lastModified": 1788405554, + "narHash": "sha256-z3ACU3NTAstjK+JNjW0zmIH2Q0GYo2pgGfJddesv7Xo=", + "rev": "a5cc6f2c37bf518436dc8d1c288ccd0c43c2f4c4", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.8954.a5cc6f2c37bf/nixexprs.tar.xz" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-26.05", + "type": "indirect" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1717432640, @@ -303,6 +317,7 @@ "flake-compat": "flake-compat_2", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs_4", + "nixpkgs-crates": "nixpkgs-crates", "rust-overlay": "rust-overlay" } }, diff --git a/packages/sequent-core/flake.nix b/packages/sequent-core/flake.nix index f9f2e06e4df..67be2b8e01d 100644 --- a/packages/sequent-core/flake.nix +++ b/packages/sequent-core/flake.nix @@ -8,6 +8,7 @@ # input inputs.rust-overlay.url = "github:oxalica/rust-overlay"; inputs.nixpkgs.url = "nixpkgs/nixos-25.05"; + inputs.nixpkgs-crates.url = "nixpkgs/nixos-26.05"; inputs.flake-utils.url = "github:numtide/flake-utils"; inputs.flake-compat = { url = "github:edolstra/flake-compat"; @@ -16,7 +17,7 @@ inputs.devenv.url = "github:cachix/devenv"; # output function of this flake - outputs = { self, nixpkgs, devenv, flake-utils, rust-overlay, flake-compat }: + outputs = { self, nixpkgs, nixpkgs-crates, devenv, flake-utils, rust-overlay, flake-compat }: flake-utils.lib.eachDefaultSystem ( system: let @@ -25,6 +26,9 @@ pkgs = import nixpkgs { inherit system overlays; }; + pkgsCrates = import nixpkgs-crates { + inherit system; + }; configureRustTargets = targets : pkgs .rust-bin .stable @@ -38,19 +42,25 @@ rust-wasm = configureRustTargets [ "wasm32-unknown-unknown" ]; rust-system = configureRustTargets []; - # Pin wasm-bindgen-cli to match the wasm-bindgen crate version in Cargo.toml (=0.2.104) - # The CLI and crate versions must match exactly - wasm-bindgen-cli-pinned = pkgs.rustPlatform.buildRustPackage rec { + # wasm-bindgen has no semver guarantee, so the CLI must match the crate + # version exactly (=0.2.123). Not in nixpkgs, so this is a source build. + # Built entirely against pkgsCrates (nixos-26.05): the crate vendorer in + # our main pin sends a default python-requests User-Agent, which crates.io + # answers with HTTP 403. The rustc that builds the CLI is 26.05's and need + # not match our 1.96.0 — only the CLI *version* must match the crate. + wasm-bindgen-cli-pinned = pkgsCrates.rustPlatform.buildRustPackage rec { pname = "wasm-bindgen-cli"; - version = "0.2.104"; + # Pinned to the wasm-bindgen crate version both Cargo workspaces use + # (packages/Cargo.toml and packages/wbraid/Cargo.toml: =0.2.123). + version = "0.2.123"; + cargoHash = "sha256-d7x6gtx5OqEE4MyT6yjYn/qtgjx7GroTpXJewnBV2dU="; src = builtins.fetchTarball { - url = "https://crates.io/api/v1/crates/${pname}/${version}/download"; - sha256 = "00bv402z5n47f7l582xmanaxraacwg2pcm6rvlcify1bn9mvwign"; + url = "https://static.crates.io/crates/${pname}/${pname}-${version}.crate"; + sha256 = "12xdns7cvnz0j26i9kryxggylsslkqs5l2b6lppfkv1bic8q0rya"; }; - cargoHash = "sha256-V0AV5jkve37a5B/UvJ9B3kwOW72vWblST8Zxs8oDctE="; - nativeBuildInputs = [ pkgs.pkg-config ]; - buildInputs = [ pkgs.openssl ] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.curl ]; + nativeBuildInputs = [ pkgsCrates.pkg-config ]; + buildInputs = [ pkgsCrates.openssl ] + ++ pkgsCrates.lib.optionals pkgsCrates.stdenv.hostPlatform.isDarwin [ pkgsCrates.curl ]; doCheck = false; }; diff --git a/packages/strand/Cargo.toml b/packages/strand/Cargo.toml index 779fe33509c..5d0ebd69eaf 100644 --- a/packages/strand/Cargo.toml +++ b/packages/strand/Cargo.toml @@ -69,7 +69,7 @@ rand_chacha = "0.9" # WASM # Note: Using specific version of wasm-bindgen to match Nix version wasm-bindgen-rayon = {version = "1.3", features = ["no-bundler"], optional = true} -wasm-bindgen = {version = "=0.2.104", optional = true} +wasm-bindgen = {version = "=0.2.123", optional = true} serde-wasm-bindgen = {version = "0.6", optional = true} web-sys = { version = "0.3", features = ['Performance', 'console'], optional = true } diff --git a/packages/strand/flake.lock b/packages/strand/flake.lock index 285b6bffc04..efb025bb92b 100644 --- a/packages/strand/flake.lock +++ b/packages/strand/flake.lock @@ -46,6 +46,20 @@ "type": "indirect" } }, + "nixpkgs-crates": { + "locked": { + "lastModified": 1788405554, + "narHash": "sha256-z3ACU3NTAstjK+JNjW0zmIH2Q0GYo2pgGfJddesv7Xo=", + "rev": "a5cc6f2c37bf518436dc8d1c288ccd0c43c2f4c4", + "type": "tarball", + "url": "https://releases.nixos.org/nixos/26.05/nixos-26.05.8954.a5cc6f2c37bf/nixexprs.tar.xz" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-26.05", + "type": "indirect" + } + }, "nixpkgs_2": { "locked": { "lastModified": 1744536153, @@ -67,6 +81,7 @@ "flake-compat": "flake-compat", "flake-utils": "flake-utils", "nixpkgs": "nixpkgs", + "nixpkgs-crates": "nixpkgs-crates", "rust-overlay": "rust-overlay" } }, diff --git a/packages/strand/flake.nix b/packages/strand/flake.nix index d98b8a86b1b..8e4080fe411 100644 --- a/packages/strand/flake.nix +++ b/packages/strand/flake.nix @@ -6,19 +6,23 @@ inputs.rust-overlay.url = "github:oxalica/rust-overlay"; inputs.nixpkgs.url = "nixpkgs/nixos-25.05"; + inputs.nixpkgs-crates.url = "nixpkgs/nixos-26.05"; inputs.flake-utils.url = "github:numtide/flake-utils"; inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; }; - outputs = { self, nixpkgs, flake-utils, rust-overlay, flake-compat }: + outputs = { self, nixpkgs, nixpkgs-crates, flake-utils, rust-overlay, flake-compat }: flake-utils.lib.eachDefaultSystem (system: let overlays = [ (import rust-overlay) ]; pkgs = import nixpkgs { inherit system overlays; }; + pkgsCrates = import nixpkgs-crates { + inherit system; + }; stdenv = pkgs.clangStdenv; configureRustTargets = targets : pkgs .rust-bin @@ -32,21 +36,29 @@ }; rust-wasm = configureRustTargets [ "wasm32-unknown-unknown" ]; rust-system = configureRustTargets []; - # Pin wasm-bindgen-cli to match the wasm-bindgen crate version in Cargo.toml (=0.2.104) - # The CLI and crate versions must match exactly - wasm-bindgen-cli-pinned = pkgs.rustPlatform.buildRustPackage rec { + + # wasm-bindgen has no semver guarantee, so the CLI must match the crate + # version exactly (=0.2.123). Not in nixpkgs, so this is a source build. + # Built entirely against pkgsCrates (nixos-26.05): the crate vendorer in + # our main pin sends a default python-requests User-Agent, which crates.io + # answers with HTTP 403. The rustc that builds the CLI is 26.05's and need + # not match our 1.96.0 — only the CLI *version* must match the crate. + wasm-bindgen-cli-pinned = pkgsCrates.rustPlatform.buildRustPackage rec { pname = "wasm-bindgen-cli"; - version = "0.2.104"; + # Pinned to the wasm-bindgen crate version both Cargo workspaces use + # (packages/Cargo.toml and packages/wbraid/Cargo.toml: =0.2.123). + version = "0.2.123"; + cargoHash = "sha256-d7x6gtx5OqEE4MyT6yjYn/qtgjx7GroTpXJewnBV2dU="; src = builtins.fetchTarball { - url = "https://crates.io/api/v1/crates/${pname}/${version}/download"; - sha256 = "00bv402z5n47f7l582xmanaxraacwg2pcm6rvlcify1bn9mvwign"; + url = "https://static.crates.io/crates/${pname}/${pname}-${version}.crate"; + sha256 = "12xdns7cvnz0j26i9kryxggylsslkqs5l2b6lppfkv1bic8q0rya"; }; - cargoHash = "sha256-V0AV5jkve37a5B/UvJ9B3kwOW72vWblST8Zxs8oDctE="; - nativeBuildInputs = [ pkgs.pkg-config ]; - buildInputs = [ pkgs.openssl ] - ++ pkgs.lib.optionals pkgs.stdenv.isDarwin [ pkgs.curl ]; + nativeBuildInputs = [ pkgsCrates.pkg-config ]; + buildInputs = [ pkgsCrates.openssl ] + ++ pkgsCrates.lib.optionals pkgsCrates.stdenv.hostPlatform.isDarwin [ pkgsCrates.curl ]; doCheck = false; }; + # see https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/rust.section.md#importing-a-cargolock-file-importing-a-cargolock-file cargoPatches = { cargoLock = let diff --git a/packages/ui-core/rust/sequent-core-0.1.0.tgz b/packages/ui-core/rust/sequent-core-0.1.0.tgz index 1df27efa16f..e0400358016 100644 Binary files a/packages/ui-core/rust/sequent-core-0.1.0.tgz and b/packages/ui-core/rust/sequent-core-0.1.0.tgz differ diff --git a/packages/voting-portal/rust/sequent-core-0.1.0.tgz b/packages/voting-portal/rust/sequent-core-0.1.0.tgz index 1df27efa16f..e0400358016 100644 Binary files a/packages/voting-portal/rust/sequent-core-0.1.0.tgz and b/packages/voting-portal/rust/sequent-core-0.1.0.tgz differ diff --git a/packages/wbraid/PROVENANCE.md b/packages/wbraid/PROVENANCE.md index ffad0200aec..b8557e3d7c1 100644 --- a/packages/wbraid/PROVENANCE.md +++ b/packages/wbraid/PROVENANCE.md @@ -91,6 +91,53 @@ nightly by enabling the named features: `shuffle_scaling` example (mostly `unwrap_used` and pedantic lints in test code, identical on nightly); that upstream state is left untouched. +## Local modifications for the devcontainer dev loop and CI + +- **Added bash twins of the five PowerShell scripts** (`build-wasm.sh`, + `serve.sh`, `test-wasm.sh`, `b4.sh`, `localstack.sh`). The `.ps1` files are + unchanged and remain the Windows dev loop. Differences beyond syntax: + `build-wasm.sh` stays on the stable toolchain and uses `RUSTC_BOOTSTRAP=1` + instead of a nightly override (the approach of + `packages/braid/scripts/build-wasm.sh`); both wasm scripts verify that the + `wasm-bindgen` CLI on `PATH` matches the version pinned in `Cargo.lock` + before building; in the devcontainer, `localstack.sh` runs LocalStack the + way every other dev service runs — as the `localstack` compose service + (opt-in `wbraid` profile in `.devcontainer/docker-compose-base.yml`, with a + `configure-localstack` one-shot creating the bucket and CORS, mirroring + `configure-minio`), addressed as `http://localstack:4566` on the project + network — while outside a compose project it keeps `localstack.ps1`'s + standalone docker-run flow; the image is pinned to `localstack/localstack:4` + everywhere (2026-era `latest` exits at startup without an auth token); + `b4.sh` defaults `AWS_ENDPOINT_URL` per environment (a pre-set value wins) + and falls back to the `amazon/aws-cli` image joined to the project network + when no AWS CLI is installed; and + `build-wasm.sh`/`serve.sh` clear an inherited `RUSTFLAGS`, which would + otherwise override the atomics rustflags in `crates/braid/.cargo/config.toml` + entirely (the devcontainer's devenv exports `RUSTFLAGS=-Awarnings`). +- **`server.py` honours a `PORT` environment variable** (default 8080, + unchanged); in the devcontainer 8080 is taken by Hasura. +- **Ran `cargo fmt`** (rustfmt 1.96.0) over the workspace — the tree was + imported unformatted — so CI can gate on `cargo fmt -- --check`. +- **Fixed the warn-level clippy findings in `braid`, `rnk` and `v2v`** so that + `cargo clippy --workspace --exclude vsc --all-targets --no-deps -- -D + warnings` passes (the CI invocation; `--no-deps` keeps `-D warnings` from + leaking into `vsc`, which every workspace clippy run otherwise compiles with + the same flags). Mechanical changes: removed clones of `Copy` types and + same-type casts, `is_multiple_of`/`filter_map`/needless-borrow cleanups, a + `&PathBuf` parameter became `&Path`, a boxed-closure type alias in a test, + and a duplicated `allow(dead_code)` removed. Three lints are allowed rather + than refactored: `too_many_arguments` on two protocol functions and one + spec-shaped RO helper, `items_after_test_module` in `v2v::wire::protinfo`, + and `inherent_to_string` in `rnk` (its `to_string` is JSON serialization + paired with `from_string`). `crates/vsc` is untouched: its lib passes clippy + at upstream's own lint levels (`cargo clippy -p vsc --no-deps`), and its test + modules/example still fail those levels as noted above. +- **Added `.github/workflows/wbraid.yml`**: fmt + clippy (the two invocations + above), `cargo test --release`, and a `wasm-core` build for + `wasm32-unknown-unknown`, on pushes/PRs touching `packages/wbraid/`. The + shared `setup-rust-tests` action gained optional `components`/`targets` + inputs for this (defaults unchanged). + ## Local modifications for clippy The tree was imported with warn-level clippy findings in `braid`, `rnk` and @@ -127,3 +174,61 @@ run) and is untouched: its lib passes, with upstream's warn-level the spec hashes. In `tests/`: needless borrows, a `&PathBuf` parameter that is now `&Path`, a duplicated `allow(dead_code)`, and a boxed-closure table that is now fn pointers behind a type alias. + +## Local modifications for the devcontainer dev loop and CI + +- **Ran `cargo fmt`** (rustfmt 1.96.0) over the workspace; the tree was imported + unformatted. +- **Added bash twins of the five PowerShell scripts** (`build-wasm.sh`, + `serve.sh`, `test-wasm.sh`, `b4.sh`, `localstack.sh`). The `.ps1` files are + unchanged and remain the Windows dev loop; flags map one-to-one + (`.\b4.ps1 -Reset -NoRun` ⇄ `./b4.sh --reset --no-run`). Differences beyond + syntax: + - `build-wasm.sh` stays on the stable toolchain and uses `RUSTC_BOOTSTRAP=1` + instead of a nightly override (the approach of + `packages/braid/scripts/build-wasm.sh`). It and `serve.sh` clear an + inherited `RUSTFLAGS`, which would otherwise replace the atomics rustflags + in `crates/braid/.cargo/config.toml` entirely (the devcontainer's devenv + exports `RUSTFLAGS=-Awarnings`). + - `build-wasm.sh` and `test-wasm.sh` verify that the `wasm-bindgen` CLI on + `PATH` matches the `Cargo.lock` pin before building. The main workspace + (`strand`, `braid`, `sequent-core`) was moved to this workspace's + `=0.2.123` pin, so the single CLI in the repository's `devenv.nix` and + `flake.nix` files serves both. + - `test-wasm.sh` accepts `geckodriver` as well as `chromedriver` + (`wasm-bindgen-test-runner` drives either); the devcontainer ships + geckodriver and Firefox. + - In the devcontainer, `localstack.sh` runs LocalStack the way every other + dev service runs: as the `localstack` compose service (opt-in `wbraid` + profile in `.devcontainer/docker-compose-base.yml`, with a + `configure-localstack` one-shot creating the bucket and applying CORS, + mirroring `configure-minio`), addressed as `http://localstack:4566` on the + project network. Outside a compose project it keeps `localstack.ps1`'s + standalone docker-run flow. The image is pinned to `localstack/localstack:4` + in both paths: from the 2026 releases on, `latest` exits at startup without + an auth token. + - `b4.sh` defaults `AWS_ENDPOINT_URL` per environment (a pre-set value wins) + and, when no AWS CLI is installed, runs the `amazon/aws-cli` image on the + project network. Linux unlinks open files without complaint, so the reset + refuses to run while a `b4v6` process exists instead of relying on a + locked-file error. +- **`server.py` honours a `PORT` environment variable** (default 8080, + unchanged); `serve.sh` falls back to `WBRAID_SERVE_PORT` for it. +- **Made the b4 listen address and the live tests' b4 URL configurable**: + `crates/b4/src/main.rs` honours `WBRAID_B4_BIND` and the two `#[ignore]`d + live-b4 tests (`protocol_test_http*.rs`) read `WBRAID_B4_URL`, both keeping + the upstream `127.0.0.1:3000` default when unset. The step devcontainer sets + them to port 3005 in `.devcontainer/.env.development`, with + `WBRAID_SERVE_PORT=8085` and `WBRAID_S3_ENDPOINT_URL=http://localstack:4566` + alongside: 3000 is the voting portal's, the host's 8080 is forwarded to + Hasura, and S3 is the `localstack` compose service. `emulator.html` keeps its + `http://127.0.0.1:3000` default; the URL field is edited by hand. +- **Added `.github/workflows/wbraid.yml`**, scoped to changes under + `packages/wbraid/`: `cargo fmt -- --check`; clippy as the two invocations + listed under "Local modifications for clippy"; `cargo test --release`, with + the live-b4 tests still `#[ignore]`d until CI has a b4 and LocalStack to run + them against; and a `wasm-core` build for `wasm32-unknown-unknown` from the + workspace root, where `crates/braid/.cargo/config.toml` does not apply, so + plain cargo suffices and no wasm-bindgen CLI is involved. The shared + `setup-rust-tests` action gained optional `components`/`targets` inputs for + this (defaults unchanged). diff --git a/packages/wbraid/TESTING.md b/packages/wbraid/TESTING.md index 15579e5d9aa..dcc332c74c0 100644 --- a/packages/wbraid/TESTING.md +++ b/packages/wbraid/TESTING.md @@ -50,19 +50,35 @@ regardless of the test. They differ in the *client* board setup: `SqlitePersistence`. ```sh -# Terminal 1: .\localstack.ps1 (S3 via LocalStack) -# Terminal 2: .\b4.ps1 (b4 server on :3000) +# Terminal 1: .\localstack.ps1 (S3 via LocalStack) [bash: ./localstack.sh] +# Terminal 2: .\b4.ps1 (b4 server on :3000) [bash: ./b4.sh] # Terminal 3: cargo test -p braid --release -- --ignored ``` +Each `.ps1` has a bash twin of the same name for the devcontainer; the flags +map one-to-one (`.\b4.ps1 -Reset -NoRun` ⇄ `./b4.sh --reset --no-run`). There, +`.devcontainer/.env.development` (exported into every devenv shell) moves b4 to +port 3005 — `WBRAID_B4_BIND` is honoured by `b4v6` and `WBRAID_B4_URL` by the +two live-b4 tests, since 3000 is the voting portal's — and points `b4.sh` at the +`localstack` service via `WBRAID_S3_ENDPOINT_URL`. Unset, everything keeps the +upstream defaults above. + ### Prerequisites - A stable Rust toolchain (for the default build). - For the live-b4 tests: **Docker** + the **AWS CLI** — `localstack.ps1` starts LocalStack, creates the `wbraid-messages` bucket, and applies `s3-cors.json` — and the **`b4`** server (`b4.ps1` sets the S3 endpoint/credentials and points - `DATABASE_URL` at a repo-root `b4.db`). + `DATABASE_URL` at a repo-root `b4.db`). In the devcontainer, `localstack.sh` + starts the `localstack` compose service instead (opt-in `wbraid` profile in + `.devcontainer/docker-compose-base.yml`) and the endpoint is + `http://localstack:4566` on the project network — `b4.sh` picks the right + endpoint automatically, and falls back to the `amazon/aws-cli` docker image + when the AWS CLI is not installed. The image is pinned to + `localstack/localstack:4`: from the 2026 releases on, `latest` exits at + startup without an auth token, so a fresh pull of `latest` (which + `localstack.ps1` does) no longer works. ## Wasm @@ -84,7 +100,7 @@ provide COOP/COEP) — backed by the native protocol tests above. ```sh # From the repo root (wbraid/), NOT crates/braid. -.\test-wasm.ps1 +.\test-wasm.ps1 # bash: ./test-wasm.sh ``` Runs a `wasm-bindgen-test` (`tests/wasm_indexeddb.rs`) exercising the @@ -113,8 +129,18 @@ validation that the protocol runs correctly under wasm. .\serve.ps1 # clears RUSTFLAGS, builds the wasm client (build-wasm.ps1, # nightly + atomics + wasm-bindgen-rayon), then serves on # :8080 with COOP/COEP (server.py) + +# bash: ./localstack.sh / ./b4.sh / ./serve.sh. In the devcontainer serve.sh +# listens on WBRAID_SERVE_PORT (8085 by default) and b4 on 3005 (WBRAID_B4_BIND), +# so open http://127.0.0.1:8085/emulator.html and set its URL field to +# http://127.0.0.1:3005. ``` +In the devcontainer, the presigned S3 URLs that b4 hands the browser point at +`http://localstack:4566` (the service's name on the project network). For the +host browser to reach them, map `localstack` to `127.0.0.1` in the host's hosts +file; the port itself is forwarded by `.devcontainer/devcontainer.json`. + Then open and: 1. **Create setup** — generates a committee, creates the DKG board on b4, posts @@ -137,12 +163,16 @@ above). - The `wasm32-unknown-unknown` target (`rustup target add wasm32-unknown-unknown`). - **`wasm-bindgen-test-runner`** (ships with `wasm-bindgen-cli`, version-matched to - the pinned `wasm-bindgen`) and **Chrome + `chromedriver`** on `PATH` — for the - headless test. + the pinned `wasm-bindgen`) and a WebDriver on `PATH` — **Chrome + + `chromedriver`**, or **Firefox + `geckodriver`** — for the headless test. The + devcontainer ships geckodriver and Firefox, and its `devenv.nix` pins the + matching `wasm-bindgen-cli` (both Cargo workspaces in the repository pin the + same `wasm-bindgen`); `test-wasm.sh` and `build-wasm.sh` check the match. - A **nightly** toolchain — for the production wasm build (`build-wasm.ps1` sets a nightly override under `crates/braid`, whose `.cargo/config.toml` forces the atomics target-features), plus **Python** for `server.py` (the COOP/COEP dev - server). + server). `build-wasm.sh` instead stays on stable and uses `RUSTC_BOOTSTRAP=1` + (the toolchain must ship `rust-src`; the devcontainer's does). - For the emulator: **Docker/LocalStack** + **`b4`**, as in the Native live-b4 prerequisites. - **`RUSTFLAGS` caveat** — clear any inherited `RUSTFLAGS` before the headless test diff --git a/packages/wbraid/b4.sh b/packages/wbraid/b4.sh new file mode 100755 index 00000000000..bb1fc41b4d9 --- /dev/null +++ b/packages/wbraid/b4.sh @@ -0,0 +1,134 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2026 Sequent Tech Inc +# +# SPDX-License-Identifier: AGPL-3.0-only + +# Run b4 against localstack, or clear everything it has accumulated. +# Bash twin of b4.ps1. +# +# ./b4.sh # run the service +# ./b4.sh --reset # delete all stored data, then run +# ./b4.sh --reset --no-run # delete and stop +# +# An unknown flag is an error. +# Dev tool: emulator runs leave boards behind that nothing will open again. + +set -euo pipefail + +CYAN=$'\e[36m' +RED=$'\e[31m' +YELLOW=$'\e[33m' +GRAY=$'\e[90m' +RESET=$'\e[0m' + +cd "$(dirname "$0")" + +RESET_DATA=0 +NO_RUN=0 +for arg in "$@"; do + case "$arg" in + --reset | --clear) RESET_DATA=1 ;; + --no-run) NO_RUN=1 ;; + *) + echo "unknown argument: $arg (expected --reset/--clear, --no-run)" >&2 + exit 2 + ;; + esac +done + +# The S3 endpoint. A pre-set AWS_ENDPOINT_URL wins; then WBRAID_S3_ENDPOINT_URL +# (.devcontainer/.env.development, exported by devenv). Without either: inside +# a compose project LocalStack is the `localstack` service on the project +# network (see localstack.sh), addressed by service name like every other dev +# service; natively it is a standalone container on localhost. +DEV_NET=$(docker inspect "$(hostname)" \ + --format '{{range $k, $v := .NetworkSettings.Networks}}{{println $k}}{{end}}' \ + 2>/dev/null | head -n 1 || true) +if [ -z "${AWS_ENDPOINT_URL:-}" ]; then + if [ -n "${WBRAID_S3_ENDPOINT_URL:-}" ]; then + AWS_ENDPOINT_URL="$WBRAID_S3_ENDPOINT_URL" + elif [ -n "$DEV_NET" ]; then + AWS_ENDPOINT_URL="http://localstack:4566" + else + AWS_ENDPOINT_URL="http://localhost:4566" + fi +fi +export AWS_ENDPOINT_URL +export AWS_ACCESS_KEY_ID="test" +export AWS_SECRET_ACCESS_KEY="test" +export AWS_REGION="us-east-1" +export S3_BUCKET_NAME="wbraid-messages" +export AWS_FORCE_PATH_STYLE="true" +export RUST_LOG="b4=info" + +# Database URL points at the workspace root b4.db +export DATABASE_URL="sqlite:$(pwd)/b4.db?mode=rwc" + +# aws CLI, or the official image when it isn't installed (the devcontainer): +# joined to the compose project network, it resolves http://localstack:4566 +# like every other service. +if command -v aws >/dev/null 2>&1; then + aws_cli() { aws "$@"; } +elif [ -n "$DEV_NET" ]; then + aws_cli() { + docker run --rm --network "$DEV_NET" \ + -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_REGION \ + amazon/aws-cli "$@" + } +else + aws_cli() { + echo "aws CLI not found on PATH" >&2 + return 127 + } +fi + +if [ "$RESET_DATA" -eq 1 ]; then + # Two stores, and both have to go. MAX_INLINE_MESSAGE_SIZE is 0, so every + # message body is in S3 and sqlite holds only metadata and the key pointing + # at it: dropping the database alone would orphan the bodies rather than + # remove them, and the bucket would keep growing. + # + # This only makes sense with the service stopped. Unlike Windows, Linux + # happily unlinks an open file, so instead of relying on a locked-file + # error, refuse the reset if a b4v6 process is running. + echo "${CYAN}Clearing b4 data...${RESET}" + + if pgrep -x b4v6 >/dev/null 2>&1; then + echo " ${RED}b4 appears to be running - stop the service and try again.${RESET}" + echo " ${GRAY}(nothing was cleared; S3 was left alone so it still matches the database)${RESET}" + exit 1 + fi + + # The database goes first, and a failure here stops the whole reset: the + # bucket must not be emptied while the database still points into it, or b4 + # comes back serving metadata for bodies that are gone -- worse than not + # having cleared at all. + if [ -e b4.db ]; then + # b4.db* also catches -wal and -shm, which sqlite may have left. + rm -f b4.db* + echo " ${GRAY}removed $(pwd)/b4.db${RESET}" + else + echo " ${GRAY}no b4.db to remove${RESET}" + fi + + # The bucket itself stays: localstack.sh recreates it idempotently and + # reapplies the CORS configuration, so emptying it avoids that step. + if aws_cli --endpoint-url="$AWS_ENDPOINT_URL" s3 rm "s3://$S3_BUCKET_NAME" --recursive >/dev/null 2>&1; then + echo " ${GRAY}emptied s3://$S3_BUCKET_NAME${RESET}" + else + echo " ${YELLOW}could not empty s3://$S3_BUCKET_NAME - is localstack running?${RESET}" + fi + + echo "" + echo "${YELLOW}Browser data is separate and is not touched by this.${RESET}" + echo "${YELLOW}In the emulator's tab: DevTools -> Application -> Storage -> Clear site data${RESET}" + echo "${GRAY}(that clears both localStorage and the per-trustee IndexedDB stores)${RESET}" + echo "" + + if [ "$NO_RUN" -eq 1 ]; then + exit 0 + fi +fi + +# Run the service from workspace root. +cargo run --bin b4v6 --release diff --git a/packages/wbraid/build-wasm.sh b/packages/wbraid/build-wasm.sh new file mode 100755 index 00000000000..ca897840c87 --- /dev/null +++ b/packages/wbraid/build-wasm.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2026 Sequent Tech Inc +# +# SPDX-License-Identifier: AGPL-3.0-only + +# Build WASM client with atomics support for wasm-bindgen-rayon. +# +# Bash twin of build-wasm.ps1 for the devcontainer, modeled on +# packages/braid/scripts/build-wasm.sh: no nightly toolchain override — +# RUSTC_BOOTSTRAP=1 lets the stable toolchain (which ships rust-src) accept +# the nightly-only bits that crates/braid/.cargo/config.toml asks for +# ([unstable] build-std and the atomics/shared-memory rustflags). +# Based on: https://github.com/huggingface/xet-core/issues/554 + +set -euo pipefail + +GREEN=$'\e[32m' +CYAN=$'\e[36m' +RED=$'\e[31m' +RESET=$'\e[0m' + +cd "$(dirname "$0")" +ROOT=$(pwd) + +# cargo resolves a relative CARGO_TARGET_DIR against the cwd, and the +# devcontainer sets a relative one (rust-local-target); anchor it here before +# cd-ing into crates/braid so this build shares the workspace's target dir. +case "${CARGO_TARGET_DIR:-}" in + "" | /*) ;; + *) export CARGO_TARGET_DIR="$ROOT/$CARGO_TARGET_DIR" ;; +esac + +# A RUSTFLAGS in the environment overrides the [target.wasm32-unknown-unknown] +# rustflags in crates/braid/.cargo/config.toml entirely (env beats config), and +# the devcontainer's devenv exports RUSTFLAGS=-Awarnings — which silently drops +# the atomics flags and fails the build inside wasm-bindgen-rayon. +unset RUSTFLAGS + +# wasm-bindgen-cli must match the wasm-bindgen crate version exactly (the +# devcontainer's devenv.nix pins the CLI to it); check before spending minutes +# on a build whose bindings can't be generated. +WANT=$(sed -n '/^name = "wasm-bindgen"$/{n;s/^version = "\(.*\)"$/\1/p}' Cargo.lock) +HAVE=$(wasm-bindgen --version 2>/dev/null | awk '{print $2}' || true) +if [ "$HAVE" != "$WANT" ]; then + echo "${RED}wasm-bindgen-cli ${HAVE:-not found} on PATH, but this workspace pins wasm-bindgen ${WANT}.${RESET}" + echo "Install the matching CLI and put it first on PATH, e.g.:" + echo " cargo install wasm-bindgen-cli --version ${WANT} --locked --root ~/.wbraid-tools" + echo " export PATH=~/.wbraid-tools/bin:\$PATH" + exit 1 +fi + +echo "${GREEN}Building WASM with atomics support...${RESET}" + +cd crates/braid + +# Build using cargo (picks up .cargo/config.toml with atomics + linker flags) +echo "${CYAN}Compiling to WASM (stable toolchain, RUSTC_BOOTSTRAP=1)...${RESET}" +if ! RUSTC_BOOTSTRAP=1 cargo build --lib --target wasm32-unknown-unknown --release --no-default-features --features wasm; then + echo "${RED}Cargo build failed!${RESET}" + exit 1 +fi + +TARGET_DIR="${CARGO_TARGET_DIR:-$ROOT/target}" +WASM_FILE="$TARGET_DIR/wasm32-unknown-unknown/release/braid.wasm" + +# Run wasm-bindgen to generate JS bindings +echo "${CYAN}Generating JS bindings with wasm-bindgen...${RESET}" +if ! wasm-bindgen "$WASM_FILE" --out-dir pkg --target web; then + echo "${RED}wasm-bindgen failed!${RESET}" + exit 1 +fi + +echo "${GREEN}Build complete! WASM bundle ready in crates/braid/pkg/${RESET}" diff --git a/packages/wbraid/crates/b4/src/main.rs b/packages/wbraid/crates/b4/src/main.rs index 438d5acf258..ae702702074 100644 --- a/packages/wbraid/crates/b4/src/main.rs +++ b/packages/wbraid/crates/b4/src/main.rs @@ -57,7 +57,8 @@ async fn main() -> Result<()> { .layer(cors) .with_state(state); - let listener = tokio::net::TcpListener::bind("127.0.0.1:3000").await?; + let bind = std::env::var("WBRAID_B4_BIND").unwrap_or_else(|_| "127.0.0.1:3000".to_string()); + let listener = tokio::net::TcpListener::bind(&bind).await?; tracing::info!( "Bulletin board service listening on {}", listener.local_addr()? diff --git a/packages/wbraid/crates/braid/src/native/test/protocol_test_http.rs b/packages/wbraid/crates/braid/src/native/test/protocol_test_http.rs index 348c84d98b4..6c0481fea07 100644 --- a/packages/wbraid/crates/braid/src/native/test/protocol_test_http.rs +++ b/packages/wbraid/crates/braid/src/native/test/protocol_test_http.rs @@ -7,7 +7,7 @@ //! b4 via [`HttpTransport`] (real HTTP + S3). //! //! This test is `#[ignore]`d (see `tests/test_protocol.rs`): it requires a running -//! b4 server at [`HTTP_URL`] backed by S3/LocalStack. Persistence is +//! b4 server at [`http_url`] backed by S3/LocalStack. Persistence is //! [`NoOpPersistence`] for now — a clean run does not exercise anti-rewrite / //! restart (that is the SQLite persistence follow-up). @@ -40,8 +40,10 @@ use crate::native::http_transport::HttpTransport; use crate::session::Session; use crate::trustee::Trustee; -/// b4 server endpoint the test drives against (must be running, with S3). -const HTTP_URL: &str = "http://127.0.0.1:3000"; +/// b4 url the test drives against. `WBRAID_B4_URL` when set, otherwise port `3000`. +fn http_url() -> String { + std::env::var("WBRAID_B4_URL").unwrap_or_else(|_| "http://127.0.0.1:3000".to_string()) +} /// Wire `date` for every message the harness posts (§3.1). const DATE: Timestamp = 0; @@ -108,14 +110,14 @@ async fn run_with_width(ciphertexts: u32) -> Result< // --- create the board on b4 and post the Configuration (manager) --- info!("Creating board {} on b4", board); - HttpTransport::create_board(HTTP_URL, &board).await?; - let manager_tx = HttpTransport::new(HTTP_URL, &board); + HttpTransport::create_board(&http_url(), &board).await?; + let manager_tx = HttpTransport::new(&http_url(), &board); Transport::::publish(&manager_tx, &cfg_message).await?; // --- one Session (trustee + board client) per configured trustee --- let mut sessions: Vec> = Vec::with_capacity(n_trustees); for (i, (signing_key, keypair)) in signing_keys.into_iter().zip(share_keypairs).enumerate() { - let transport = HttpTransport::new(HTTP_URL, &board); + let transport = HttpTransport::new(&http_url(), &board); let client = BoardClient::connect(transport, NoOpPersistence).await?; let trustee = Trustee::new( (i + 1).to_string(), diff --git a/packages/wbraid/crates/braid/src/native/test/protocol_test_http_union.rs b/packages/wbraid/crates/braid/src/native/test/protocol_test_http_union.rs index 17560153d99..1ca80740b18 100644 --- a/packages/wbraid/crates/braid/src/native/test/protocol_test_http_union.rs +++ b/packages/wbraid/crates/braid/src/native/test/protocol_test_http_union.rs @@ -13,7 +13,7 @@ //! SQLite persistence path and the union seed against a real board. //! //! `#[ignore]`d (see `tests/test_protocol.rs`): it requires a running b4 at -//! [`HTTP_URL`] backed by S3/LocalStack. +//! [`http_url`] backed by S3/LocalStack. use anyhow::{anyhow, Result}; use log::info; @@ -45,8 +45,10 @@ use crate::native::http_transport::HttpTransport; use crate::native::persistence::SqlitePersistence; use crate::trustee::Trustee; -/// b4 server endpoint the test drives against (must be running, with S3). -const HTTP_URL: &str = "http://127.0.0.1:3000"; +/// b4 url the test drives against. `WBRAID_B4_URL` when set, otherwise port `3000`. +fn http_url() -> String { + std::env::var("WBRAID_B4_URL").unwrap_or_else(|_| "http://127.0.0.1:3000".to_string()) +} /// Wire `date` for every message the harness posts (§3.1). const DATE: Timestamp = 0; @@ -125,8 +127,8 @@ async fn run_with_width( // --- phase 1: DKG on the shared parent board (with SQLite persistence) --- info!("Creating DKG board {} on b4", dkg_board); - HttpTransport::create_board(HTTP_URL, &dkg_board).await?; - let dkg_manager_tx = HttpTransport::new(HTTP_URL, &dkg_board); + HttpTransport::create_board(&http_url(), &dkg_board).await?; + let dkg_manager_tx = HttpTransport::new(&http_url(), &dkg_board); Transport::::publish(&dkg_manager_tx, &cfg_message).await?; let mut dkg_clients: Vec> = @@ -135,7 +137,7 @@ async fn run_with_width( let path = temp_db(&format!("dkg_{}_{}", run_id, i)); dkg_clients.push( BoardClient::connect( - HttpTransport::new(HTTP_URL, &dkg_board), + HttpTransport::new(&http_url(), &dkg_board), SqlitePersistence::open(&path)?, ) .await?, @@ -174,7 +176,7 @@ async fn run_with_width( for tally in 0..tallies { let tally_board = format!("uniontally_{}_{}", run_id, tally); info!("Creating tally board {} on b4", tally_board); - HttpTransport::create_board(HTTP_URL, &tally_board).await?; + HttpTransport::create_board(&http_url(), &tally_board).await?; // Manager encrypts a fresh ciphertext set and posts the ballots. let mut enc_rng = C::get_rng(); @@ -197,7 +199,7 @@ async fn run_with_width( 1 + tally as u128, &ballots, ); - let tally_manager_tx = HttpTransport::new(HTTP_URL, &tally_board); + let tally_manager_tx = HttpTransport::new(&http_url(), &tally_board); Transport::::publish(&tally_manager_tx, &ballots_message).await?; // One union client per trustee: child (tally) ∪ parent (DKG), seeded with @@ -208,8 +210,8 @@ async fn run_with_width( let path = temp_db(&format!("tally_{}_{}_{}", run_id, tally, i)); tally_clients.push( BoardClient::connect_union( - HttpTransport::new(HTTP_URL, &tally_board), - HttpTransport::new(HTTP_URL, &dkg_board), + HttpTransport::new(&http_url(), &tally_board), + HttpTransport::new(&http_url(), &dkg_board), SqlitePersistence::open(&path)?, seed.clone(), ) diff --git a/packages/wbraid/localstack.sh b/packages/wbraid/localstack.sh new file mode 100755 index 00000000000..cae8840644d --- /dev/null +++ b/packages/wbraid/localstack.sh @@ -0,0 +1,95 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2026 Sequent Tech Inc +# +# SPDX-License-Identifier: AGPL-3.0-only + +# Start a fresh LocalStack and create the wbraid-messages S3 bucket with CORS. +# Bash twin of localstack.ps1. +# +# In the devcontainer, LocalStack is the `localstack` compose service declared +# in .devcontainer/docker-compose-base.yml (opt-in `wbraid` profile), living on +# the project network like every other dev service; the endpoint there is +# http://localstack:4566, which b4.sh picks up automatically. Outside a compose +# project — a native Linux checkout — this behaves like localstack.ps1: a +# standalone container publishing localhost:4566. + +set -euo pipefail + +cd "$(dirname "$0")" + +# Pinned here and in the compose service: from the 2026 calendar releases on, +# localstack/localstack:latest demands an auth token at startup and exits +# without one, so a fresh pull of `latest` breaks. The 4.x line runs +# unauthenticated. +IMAGE="localstack/localstack:4" + +COMPOSE_PROJECT=$(docker inspect "$(hostname)" \ + --format '{{ index .Config.Labels "com.docker.compose.project" }}' \ + 2>/dev/null || true) + +if [ -n "$COMPOSE_PROJECT" ]; then + # The devcontainer: drive the project's own compose services. Targeting a + # service by name auto-enables its `wbraid` profile, and --force-recreate + # gives the same start-fresh semantic as the standalone path below. The + # config's bind mounts need host paths, which .devcontainer/.env carries + # (LOCAL_WORKSPACE_FOLDER). + REPO_ROOT=$(cd ../.. && pwd) + compose() { + # IGNORE_ORPHANS: containers from older revisions of the compose file + # may exist in the project; they are not this script's business (and + # the --remove-orphans hint compose would print must not be followed) + COMPOSE_IGNORE_ORPHANS=1 docker compose -p "$COMPOSE_PROJECT" \ + -f "$REPO_ROOT/.devcontainer/docker-compose.yml" \ + --env-file "$REPO_ROOT/.devcontainer/.env" "$@" + } + compose up -d --force-recreate localstack + # One-shot bucket + CORS provisioning, in the foreground so a failure + # shows up here + compose run --rm configure-localstack + echo "LocalStack ready at ${WBRAID_S3_ENDPOINT_URL:-http://localstack:4566} (s3://wbraid-messages with CORS applied)." + exit 0 +fi + +# --- Standalone (no compose project): the localstack.ps1 flow --------------- + +if ! command -v aws >/dev/null 2>&1; then + echo "aws CLI not found on PATH (needed to create the bucket and apply CORS)." >&2 + exit 1 +fi + +# Stop and remove existing LocalStack containers (if any); the bare image name +# also catches :latest strays from earlier runs +for image in localstack/localstack "$IMAGE"; do + docker ps -q --filter "ancestor=$image" | xargs -r docker stop + docker ps -aq --filter "ancestor=$image" | xargs -r docker rm +done + +# Set dummy AWS credentials for LocalStack +export AWS_ACCESS_KEY_ID="test" +export AWS_SECRET_ACCESS_KEY="test" +export AWS_DEFAULT_REGION="us-east-1" + +# Start with new configuration +docker run -d -p 4566:4566 -p 4510-4559:4510-4559 \ + -e HOSTNAME_EXTERNAL=localhost \ + -e S3_HOSTNAME=localhost:4566 \ + "$IMAGE" + +# Ready in a few seconds warm; a cold start (first pull) outlives a fixed sleep +echo "Waiting for LocalStack on localhost:4566..." +for _ in $(seq 1 45); do + if curl -sf --max-time 2 http://localhost:4566/_localstack/health >/dev/null 2>&1; then + break + fi + sleep 2 +done + +# Create bucket and configure CORS (ignore error if bucket already exists) +if ! aws --endpoint-url=http://localhost:4566 s3 mb s3://wbraid-messages 2>/dev/null; then + echo "Bucket wbraid-messages already exists or creation failed, continuing..." +fi + +aws --endpoint-url=http://localhost:4566 s3api put-bucket-cors \ + --bucket wbraid-messages --cors-configuration file://s3-cors.json + +echo "LocalStack ready: s3://wbraid-messages exists with CORS applied." diff --git a/packages/wbraid/serve.sh b/packages/wbraid/serve.sh new file mode 100755 index 00000000000..c8d6b54cb3f --- /dev/null +++ b/packages/wbraid/serve.sh @@ -0,0 +1,32 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2026 Sequent Tech Inc +# +# SPDX-License-Identifier: AGPL-3.0-only + +# Build and serve the braid WASM client with atomics support. +# Bash twin of serve.ps1. + +set -euo pipefail + +GREEN=$'\e[32m' +RED=$'\e[31m' +RESET=$'\e[0m' + +cd "$(dirname "$0")" + +# Clear any inherited RUSTFLAGS that might interfere with .cargo/config.toml +# (the devcontainer's devenv exports RUSTFLAGS=-Awarnings). +unset RUSTFLAGS + +if ! ./build-wasm.sh; then + echo "${RED}Build failed, not starting server${RESET}" + exit 1 +fi + +# PORT, else WBRAID_SERVE_PORT, else the wbraid default, 8080. +PORT="${PORT:-${WBRAID_SERVE_PORT:-8080}}" +export PORT + +echo "${GREEN}Starting development server on http://127.0.0.1:${PORT}${RESET}" +echo "${GREEN}Open http://127.0.0.1:${PORT}/emulator.html${RESET}" +python3 server.py diff --git a/packages/wbraid/server.py b/packages/wbraid/server.py index ceefe05843c..98303c7c275 100644 --- a/packages/wbraid/server.py +++ b/packages/wbraid/server.py @@ -2,6 +2,7 @@ # # SPDX-License-Identifier: AGPL-3.0-only +import os from http.server import HTTPServer, SimpleHTTPRequestHandler class CrossOriginIsolation(SimpleHTTPRequestHandler): @@ -18,7 +19,9 @@ def end_headers(self): '.js': 'text/javascript', }) -print("Launching server on 127.0.0.1:8080..") +port = int(os.environ.get('PORT', '8080')) + +print(f"Launching server on 127.0.0.1:{port}..") print("SharedArrayBuffer support enabled (Cross-Origin-Isolation headers)") -httpd = HTTPServer(('127.0.0.1', 8080), handler) +httpd = HTTPServer(('127.0.0.1', port), handler) httpd.serve_forever() diff --git a/packages/wbraid/test-wasm.sh b/packages/wbraid/test-wasm.sh new file mode 100755 index 00000000000..5919735ac6a --- /dev/null +++ b/packages/wbraid/test-wasm.sh @@ -0,0 +1,59 @@ +#!/usr/bin/env bash +# SPDX-FileCopyrightText: 2026 Sequent Tech Inc +# +# SPDX-License-Identifier: AGPL-3.0-only + +# Headless-browser test for the wasm IndexedDB persistence backend (M3-B). +# Bash twin of test-wasm.ps1. +# +# Runs the `wasm-core` build (no `wasm-bindgen-rayon`, hence no atomics / shared +# memory), so it works in a plain headless browser with no SharedArrayBuffer / +# COOP-COEP setup. The production browser build is unaffected: `build-wasm.sh` +# still uses `--features wasm`, which adds the `wasm-bindgen-rayon` thread pool. +# +# IMPORTANT: runs from the repo root (this directory), NOT crates/braid, so the +# atomics `.cargo/config.toml` in crates/braid is not applied. +# +# Prerequisites: `wasm-bindgen-test-runner` (ships with wasm-bindgen-cli) and a +# WebDriver on PATH: `chromedriver` matching your Chrome, or `geckodriver` with +# Firefox (what the devcontainer ships). The runner takes whichever it finds. + +set -euo pipefail + +GREEN=$'\e[32m' +RED=$'\e[31m' +RESET=$'\e[0m' + +cd "$(dirname "$0")" + +# The test runner must match the wasm-bindgen crate version exactly (the +# devcontainer's devenv.nix pins the CLI to it). +WANT=$(sed -n '/^name = "wasm-bindgen"$/{n;s/^version = "\(.*\)"$/\1/p}' Cargo.lock) +HAVE=$(wasm-bindgen-test-runner --version 2>/dev/null | awk '{print $2}' || true) +if [ "$HAVE" != "$WANT" ]; then + echo "${RED}wasm-bindgen-test-runner ${HAVE:-not found} on PATH, but this workspace pins wasm-bindgen ${WANT}.${RESET}" + echo "Install the matching CLI and put it first on PATH, e.g.:" + echo " cargo install wasm-bindgen-cli --version ${WANT} --locked --root ~/.wbraid-tools" + echo " export PATH=~/.wbraid-tools/bin:\$PATH" + exit 1 +fi +if ! command -v chromedriver >/dev/null 2>&1 && ! command -v geckodriver >/dev/null 2>&1; then + echo "${RED}no WebDriver on PATH: need chromedriver (matching your Chrome) or geckodriver (Firefox).${RESET}" + exit 1 +fi + +echo "${GREEN}Running wasm IndexedDB test in a headless browser...${RESET}" + +export CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUNNER="wasm-bindgen-test-runner" +# Set NO_HEADLESS=1 in your shell to watch the browser. + +if cargo test -p braid \ + --no-default-features --features wasm-core \ + --target wasm32-unknown-unknown \ + --test wasm_indexeddb; then + echo "${GREEN}wasm IndexedDB test passed.${RESET}" +else + code=$? + echo "${RED}wasm IndexedDB test failed (exit $code).${RESET}" + exit $code +fi diff --git a/packages/yarn.lock b/packages/yarn.lock index 31dc6204435..0290c0c2381 100644 --- a/packages/yarn.lock +++ b/packages/yarn.lock @@ -7735,7 +7735,7 @@ braces@^2.3.2, braces@^3.0.3, braces@~3.0.2: "braid-wasm@file:./admin-portal/rust/braid-wasm-0.1.0.tgz": version "0.1.0" - resolved "file:./admin-portal/rust/braid-wasm-0.1.0.tgz#d3dfab19ca27d43bbfffb96654857766709dfd77" + resolved "file:./admin-portal/rust/braid-wasm-0.1.0.tgz#e9e3df52efe38dff1c47370611ca226ac3d68143" brorand@^1.0.1, brorand@^1.1.0: version "1.1.0" @@ -17506,15 +17506,15 @@ sentence-case@^3.0.4: "sequent-core@file:./admin-portal/rust/sequent-core-0.1.0.tgz": version "0.1.0" - resolved "file:./admin-portal/rust/sequent-core-0.1.0.tgz#cec4ae709ac8734aed975604bd5107bc57d6898a" + resolved "file:./admin-portal/rust/sequent-core-0.1.0.tgz#eec08b2d417036637c08bdde56c4712ff4a47cfd" "sequent-core@file:./ballot-verifier/rust/sequent-core-0.1.0.tgz": version "0.1.0" - resolved "file:./ballot-verifier/rust/sequent-core-0.1.0.tgz#cec4ae709ac8734aed975604bd5107bc57d6898a" + resolved "file:./ballot-verifier/rust/sequent-core-0.1.0.tgz#eec08b2d417036637c08bdde56c4712ff4a47cfd" "sequent-core@file:./voting-portal/rust/sequent-core-0.1.0.tgz": version "0.1.0" - resolved "file:./voting-portal/rust/sequent-core-0.1.0.tgz#cec4ae709ac8734aed975604bd5107bc57d6898a" + resolved "file:./voting-portal/rust/sequent-core-0.1.0.tgz#eec08b2d417036637c08bdde56c4712ff4a47cfd" serialize-javascript@^6.0.0, serialize-javascript@^6.0.2: version "6.0.2"