diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..9e12940 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,60 @@ +# Changelog + +All notable changes to `bspctl` will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +--- + +## [Unreleased] + +### Added +- `examples/` directory with runnable bash scripts for the three core flows: + - `create-beo.sh` — bootstrap a sovereign biological identity + - `grant-consent.sh` — issue a ConsentToken to an IEO + - `submit-biorecord.sh` — submit measurements with scoped consent +- `CONTRIBUTING.md` with dev setup, testing, and PR guidelines +- Expanded README with per-command reference tables and flag documentation + +### Changed +- Documentation consolidated with cross-links to bsp-spec glossary and error catalog + +--- + +## [0.2.0] — 2026-04 + +### Added +- Full 22-command coverage: BEO, IEO, Consent, Exchange, Config +- `bsp destroy` — cryptographic erasure (LGPD Art. 18 / GDPR Art. 17) +- `bsp consent revoke-all` — emergency revocation +- `bsp export` — FHIR R4 / JSON / CSV portability (GDPR Art. 20) +- `bsp rotate-key` — rotate Ed25519 key +- `bsp ieo create|get|list|lock|unlock|destroy` — institutional lifecycle +- `bsp lock` / `bsp unlock` — BEO-level emergency freeze +- Structured error output with stable codes (see `bsp-spec/docs/ERROR_CODES.md`) +- Nonce + timestamp replay protection on all signed payloads + +### Security +- All Ed25519 operations happen locally — private key never transmitted +- `--confirm` flag required for destructive operations +- Max request timestamp age: 5 minutes +- Minimum nonce length: 16 characters + +--- + +## [0.1.0] — 2026-03 + +### Added +- Initial CLI with `create`, `resolve`, `consent grant`, `consent revoke` +- Configuration at `~/.bsp/config.json` +- Testnet + mainnet support +- Published to npm as `bspctl` + +--- + +## Links + +- **Protocol spec:** [bsp-spec](https://github.com/Biological-Sovereignty-Protocol/bsp-spec) +- **SDK:** [bsp-sdk-typescript](https://github.com/Biological-Sovereignty-Protocol/bsp-sdk-typescript) +- **Issues:** [github.com/.../bsp-cli/issues](https://github.com/Biological-Sovereignty-Protocol/bsp-cli/issues) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..de6280d --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,137 @@ +# Contributing to bspctl + +Thank you for helping make the Biological Sovereignty Protocol better. `bspctl` is the official command-line interface for BSP, so every change here reaches every developer, every terminal, every sovereign identity. + +This document is the fastest path from "I want to contribute" to "my PR is merged". + +--- + +## Before you start + +- **Read the spec** — `bsp-spec` defines the protocol. Every CLI command maps to a spec operation. If behavior disagrees with the spec, the spec wins. +- **Check existing issues** — someone may already be working on it. +- **Open an issue first** — for non-trivial changes, align on approach before you code. + +--- + +## Development setup + +```bash +git clone https://github.com/Biological-Sovereignty-Protocol/bsp-cli +cd bsp-cli +npm install +npm run build +node dist/index.js --help +``` + +Requires Node.js >= 18. + +### Local testing + +```bash +# Link the CLI globally for live testing +npm link +bsp --help + +# When done +npm unlink +``` + +### Running against testnet + +```bash +bsp config set network testnet +bsp config set registry https://api-testnet.biologicalsovereigntyprotocol.com +``` + +Never test destructive operations (`destroy`, `revoke-all`) against mainnet. + +--- + +## Pull request checklist + +Before you open a PR: + +- [ ] `npm run build` passes with no TypeScript errors +- [ ] Commands added / changed are documented in `README.md` (commands table + example) +- [ ] `CHANGELOG.md` updated under `[Unreleased]` +- [ ] New error conditions map to a code in `bsp-spec/docs/ERROR_CODES.md` (add one if needed, cross-link the PR) +- [ ] Destructive operations require `--confirm` +- [ ] No private keys, tokens, or identifiable data in test fixtures +- [ ] PR description explains **why** the change is needed, not only what it does + +--- + +## Coding style + +- **TypeScript strict mode** — no `any` unless unavoidable and commented +- **No cacoete de IA** — frases curtas, sem ponto-e-vírgula decorativo, sem "é importante notar que" +- **Error messages** — human-readable on stderr, exit code 1 on failure, include actionable next step +- **Success output** — prefix with `✓`, errors with `✗`, warnings with `⚠️` +- **No colors when piped** — respect `process.stdout.isTTY` +- **JSON mode** — any command showing data MUST support `--json` for scripting + +--- + +## Commit messages + +Follow [Conventional Commits](https://www.conventionalcommits.org/): + +``` +feat(consent): add --dry-run to consent grant +fix(beo): handle BEO_DESTROYED gracefully on resolve +docs(readme): clarify private-key storage warning +chore(deps): bump @bsp/sdk to 0.3.1 +``` + +Scope is the command group: `beo`, `ieo`, `consent`, `exchange`, `config`, or `cli` for cross-cutting. + +--- + +## Adding a new command + +1. Create `src/commands/.ts` (or extend existing) with the Commander definition +2. Wire it into `src/index.ts` +3. Add a row to the relevant command table in `README.md` +4. Document every flag (required / optional / default) +5. Add an example invocation +6. Add a `CHANGELOG.md` entry under `[Unreleased]` +7. If the command needs a new error code, coordinate with `bsp-spec/docs/ERROR_CODES.md` in the same PR + +--- + +## Security + +- **Keys are sacred.** Any code path that touches the private key must be reviewed by a maintainer before merge. +- **Never log the private key** — not even at `--debug` level. +- **No phone-home telemetry** — the CLI must work air-gapped. +- **Report vulnerabilities privately** — see `SECURITY.md`. + +--- + +## Release + +Maintainers only: + +```bash +# 1. Bump version in package.json +# 2. Move [Unreleased] → new version in CHANGELOG.md +# 3. Tag +git tag v0.3.0 +git push --tags + +# 4. Publish +npm publish +``` + +--- + +## License + +By contributing, you agree that your contributions are licensed under Apache 2.0. + +## Related + +- **Protocol spec:** [bsp-spec](https://github.com/Biological-Sovereignty-Protocol/bsp-spec) +- **SDK:** [bsp-sdk-typescript](https://github.com/Biological-Sovereignty-Protocol/bsp-sdk-typescript) +- **Security policy:** [`SECURITY.md`](./SECURITY.md) diff --git a/README.md b/README.md index b57a5fd..f7db665 100644 --- a/README.md +++ b/README.md @@ -285,6 +285,150 @@ The CLI prints human-readable errors and exits with code 1 on failure: --- +## Command Reference — Detailed + +Every command, every flag, every example. Reach for this when you want exhaustive detail. + +### `bsp create ` + +Create a new BEO. Generates an Ed25519 keypair **locally** — the private key never leaves your machine. + +| Flag | Required | Default | Description | +|------|----------|---------|-------------| +| `` | Yes | — | `.bsp` domain (e.g. `alice.bsp`) | +| `--json` | No | off | Emit output as JSON for scripting | + +```bash +bsp create alice.bsp +bsp create alice.bsp --json > identity.json +``` + +### `bsp resolve ` + +Resolve a BEO by its `.bsp` domain. Reads on-chain state — no signature required. + +```bash +bsp resolve alice.bsp +``` + +### `bsp lock ` / `bsp unlock ` + +Emergency lock or unlock a BEO. Requires the holder's private key. Locked BEOs reject all operations until unlocked. + +### `bsp rotate-key ` + +Rotate the BEO's Ed25519 key. Increments `keyVersion`. Old signatures remain valid for past records. + +### `bsp destroy --confirm` + +**IRREVERSIBLE.** Cryptographic erasure (LGPD Art. 18 / GDPR Art. 17). `--confirm` flag is mandatory. + +| Flag | Required | Description | +|------|----------|-------------| +| `` | Yes | Target BEO | +| `--confirm` | Yes | Explicit confirmation — prevents accidental erasure | + +### `bsp consent grant ` + +Issue a ConsentToken to an institution. + +| Flag | Required | Default | Description | +|------|----------|---------|-------------| +| `--intents ` | Yes | — | Comma-separated: `SUBMIT_RECORD`, `READ_RECORDS`, `ANALYZE_VITALITY`, `REQUEST_SCORE`, `EXPORT_DATA`, `SYNC_PROTOCOL` | +| `--categories ` | No | all | Comma-separated BSP categories (e.g. `BSP-LA,BSP-CV`) | +| `--days ` | No | permanent | Expiration in days | + +```bash +bsp consent grant \ + --intents SUBMIT_RECORD,READ_RECORDS \ + --categories BSP-LA,BSP-GL,BSP-HM \ + --days 365 +``` + +### `bsp consent revoke ` + +Revoke a single token. Effect is immediate on-chain. + +### `bsp consent revoke-all --confirm` + +Revoke **every** active ConsentToken for a BEO. Use in emergency (lost device, compromised identity). + +### `bsp consent verify ` + +Check if a token is valid — returns status (active / revoked / expired), intents, categories, expiry. + +### `bsp consent list ` + +List all tokens for a BEO. Supports `--json`. + +### `bsp ieo create ` + +Register a new IEO on the protocol. + +| Flag | Required | Default | Description | +|------|----------|---------|-------------| +| `` | Yes | — | Institution `.bsp` domain (e.g. `fleury.bsp`) | +| `--type ` | Yes | — | `LAB` \| `HOSPITAL` \| `WEARABLE` \| `PHYSICIAN` \| `INSURER` \| `RESEARCH` \| `PLATFORM` | +| `--name ` | Yes | — | Human-readable institution name | + +### `bsp ieo get ` / `bsp ieo list` + +Retrieve IEO details or list IEOs. `list` supports filters: `--type`, `--status`, `--cert`. + +### `bsp ieo lock|unlock|destroy` + +Lifecycle operations on an IEO. `destroy` requires `--confirm`. + +### `bsp records submit ` + +Submit BioRecords from a JSON file. Signed by the IEO. + +| Flag | Required | Description | +|------|----------|-------------| +| `--token ` | Yes | Active ConsentToken with `SUBMIT_RECORD` intent | +| `--file ` | Yes | JSON file containing an array of BioRecord payloads | + +### `bsp records read ` + +Read BioRecords with filters. + +| Flag | Required | Default | Description | +|------|----------|---------|-------------| +| `--token ` | Yes | — | ConsentToken with `READ_RECORDS` intent | +| `--categories ` | No | all | Comma-separated category codes | +| `--from ` | No | — | ISO 8601 start date | +| `--to ` | No | — | ISO 8601 end date | +| `--json` | No | off | JSON output | + +### `bsp export ` + +Sovereign data export (GDPR Art. 20). + +| Flag | Required | Default | Description | +|------|----------|---------|-------------| +| `--token ` | Yes | — | Token with `EXPORT_DATA` intent | +| `--format ` | No | `JSON` | `JSON` \| `CSV` \| `FHIR_R4` | + +### `bsp config set|get|show|path` + +Manage the config at `~/.bsp/config.json`. See the `Configuration` section above for recognized keys. + +--- + +## Examples + +Runnable bash scripts in [`examples/`](./examples): + +- [`examples/create-beo.sh`](./examples/create-beo.sh) — bootstrap a sovereign biological identity +- [`examples/grant-consent.sh`](./examples/grant-consent.sh) — issue a ConsentToken to an IEO +- [`examples/submit-biorecord.sh`](./examples/submit-biorecord.sh) — submit measurements with scoped consent + +--- + +## Changelog + +See [`CHANGELOG.md`](./CHANGELOG.md). + ## Related Packages | Package | Description | diff --git a/examples/create-beo.sh b/examples/create-beo.sh new file mode 100755 index 0000000..51f7795 --- /dev/null +++ b/examples/create-beo.sh @@ -0,0 +1,50 @@ +#!/usr/bin/env bash +# ────────────────────────────────────────────────────────────── +# BSP CLI — Create a Biological Entity Object (BEO) +# ────────────────────────────────────────────────────────────── +# This script walks through creating a sovereign biological +# identity on BSP. Keys are generated locally and never leave +# your machine. +# +# Usage: ./create-beo.sh +# Example: ./create-beo.sh alice.bsp +# ────────────────────────────────────────────────────────────── + +set -euo pipefail + +DOMAIN="${1:-}" + +if [[ -z "$DOMAIN" ]]; then + echo "usage: $0 " + echo "example: $0 alice.bsp" + exit 1 +fi + +if [[ ! "$DOMAIN" =~ \.bsp$ ]]; then + echo "error: domain must end in .bsp (got: $DOMAIN)" + exit 1 +fi + +echo "─── 1. Configure network ───" +bsp config set network testnet + +echo +echo "─── 2. Create BEO for $DOMAIN ───" +echo "Note: private key + seed will be shown ONCE. Store them offline." +bsp create "$DOMAIN" + +echo +echo "─── 3. After you save the private key, set it in config ───" +echo "run: bsp config set private-key " + +echo +echo "─── 4. Verify your BEO exists on-chain ───" +read -rp "Press Enter once you have saved the key and set it in config..." +bsp resolve "$DOMAIN" + +echo +echo "Done. Your sovereign biological identity is live." +echo "Domain: $DOMAIN" +echo "Next steps:" +echo " - Grant consent to an IEO: see ./grant-consent.sh" +echo " - Submit biological records: see ./submit-biorecord.sh" diff --git a/examples/grant-consent.sh b/examples/grant-consent.sh new file mode 100755 index 0000000..b25fe51 --- /dev/null +++ b/examples/grant-consent.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# ────────────────────────────────────────────────────────────── +# BSP CLI — Grant ConsentToken to an IEO +# ────────────────────────────────────────────────────────────── +# This script issues a ConsentToken from a BEO (patient / holder) +# to an IEO (lab / hospital / wearable), scoped to specific +# intents and categories with an expiry. +# +# Usage: ./grant-consent.sh +# Example: ./grant-consent.sh tx_abc123... ieo_def456... +# ────────────────────────────────────────────────────────────── + +set -euo pipefail + +BEO_ID="${1:-}" +IEO_ID="${2:-}" + +if [[ -z "$BEO_ID" || -z "$IEO_ID" ]]; then + echo "usage: $0 " + echo "example: $0 tx_abc123... ieo_def456..." + echo + echo "tip: resolve a .bsp domain to get its ID" + echo " bsp resolve alice.bsp" + echo " bsp ieo list --type LAB" + exit 1 +fi + +# Defaults — adjust per use case +INTENTS="${INTENTS:-SUBMIT_RECORD,READ_RECORDS}" +CATEGORIES="${CATEGORIES:-BSP-LA,BSP-HM,BSP-GL}" +DAYS="${DAYS:-365}" + +echo "─── Granting ConsentToken ───" +echo " BEO $BEO_ID" +echo " IEO $IEO_ID" +echo " Intents $INTENTS" +echo " Categories $CATEGORIES" +echo " Expires $DAYS days" +echo + +read -rp "Confirm? (y/N) " confirm +[[ "$confirm" == "y" ]] || { echo "aborted"; exit 1; } + +bsp consent grant "$BEO_ID" "$IEO_ID" \ + --intents "$INTENTS" \ + --categories "$CATEGORIES" \ + --days "$DAYS" + +echo +echo "─── Verify tokens on your BEO ───" +bsp consent list "$BEO_ID" + +echo +echo "Done. To revoke later:" +echo " bsp consent revoke $BEO_ID" +echo "To emergency-revoke ALL tokens:" +echo " bsp consent revoke-all $BEO_ID --confirm" diff --git a/examples/submit-biorecord.sh b/examples/submit-biorecord.sh new file mode 100755 index 0000000..303694b --- /dev/null +++ b/examples/submit-biorecord.sh @@ -0,0 +1,74 @@ +#!/usr/bin/env bash +# ────────────────────────────────────────────────────────────── +# BSP CLI — Submit BioRecords to a BEO +# ────────────────────────────────────────────────────────────── +# This script submits biological measurements (blood test, +# wearable readings, etc.) from an IEO to a BEO, authorized by +# a ConsentToken with SUBMIT_RECORD intent. +# +# Usage: ./submit-biorecord.sh +# Example: ./submit-biorecord.sh tx_abc123 tok_xyz789 results.json +# ────────────────────────────────────────────────────────────── + +set -euo pipefail + +BEO_ID="${1:-}" +TOKEN_ID="${2:-}" +FILE="${3:-}" + +if [[ -z "$BEO_ID" || -z "$TOKEN_ID" || -z "$FILE" ]]; then + cat < + +example: $0 tx_abc123... tok_xyz789... ./blood-panel.json + +records-file.json format: +[ + { + "categoryCode": "BSP-HM", + "biomarkerCode": "BSP-HM-HGB", + "value": 14.2, + "unit": "g/dL", + "referenceRange": { "min": 12.0, "max": 16.0 }, + "collectedAt": "2026-04-15T08:30:00Z" + }, + { + "categoryCode": "BSP-HM", + "biomarkerCode": "BSP-HM-HCT", + "value": 42.1, + "unit": "%", + "referenceRange": { "min": 36, "max": 48 }, + "collectedAt": "2026-04-15T08:30:00Z" + } +] + +required: + - IEO private key set in config (bsp config set private-key ...) + - ConsentToken with SUBMIT_RECORD intent matching your IEO +EOF + exit 1 +fi + +if [[ ! -f "$FILE" ]]; then + echo "error: file not found: $FILE" + exit 1 +fi + +echo "─── 1. Verify the ConsentToken is valid ───" +bsp consent verify "$TOKEN_ID" + +echo +echo "─── 2. Submit BioRecords ───" +bsp records submit "$BEO_ID" \ + --token "$TOKEN_ID" \ + --file "$FILE" + +echo +echo "─── 3. (Optional) Read back the records you just submitted ───" +read -rp "Read back? (y/N) " rb +if [[ "$rb" == "y" ]]; then + bsp records read "$BEO_ID" --token "$TOKEN_ID" --json | head -40 +fi + +echo +echo "Done. Records are permanently stored on Arweave."