# drs-sdk — Component Documentation

## Scope

The TypeScript SDK covers the **issuance path only**.

Verification is `drs-verify`'s job. The SDK calls drs-verify over HTTP (via `VerifyClient`)
or, in browser environments, optionally uses the Rust WASM module for client-side verification.

---

## Why TypeScript Here

- Delegation issuance is low-frequency (human interaction, tool setup)
- Developer-facing SDK: npm ecosystem, IDE tooling, browser compatibility
- All crypto is delegated to audited libraries — no hand-rolled primitives
- `@noble/ed25519` is used for Ed25519 signing (audited, no WebCrypto dependency on hot paths)

---

## Why `@noble/ed25519` and Not `jose`

`jose` supports EdDSA via `jose.SignJWT` but requires the Web Crypto API's
`SubtleCrypto.importKey` for Ed25519 key import. Compatibility varies by runtime.
`@noble/ed25519` provides a deterministic, audited implementation with no runtime
dependencies — consistent across Node 20+, Deno, and browsers.

The technical audit (§9) flagged `jsonwebtoken` for limited EdDSA support;
`@noble/ed25519` addresses this directly.

---

## Why Policy Attenuation Is Checked at Issuance

A sub-delegation that escalates policy will fail Block D of chain verification.
But the failure only surfaces when the chain is presented to drs-verify — after
the sub-delegation has already been signed and possibly distributed.

By checking attenuation at issuance in `issueSubDelegation`, invalid chains
are prevented at the source. The `DrsError` with code `POLICY_ESCALATION` tells
the SDK consumer exactly what went wrong before any signing occurs.

---

## WASM Integration

The WASM module is generated by `wasm-pack` from `drs-core`:

```sh
cd drs-core
wasm-pack build --target web --features wasm
# Output: drs-core/pkg/ — publish as @drs/wasm
```

The `src/wasm/loader.ts` module:
- Is idempotent: `initWasm()` can be called multiple times safely
- Is lazy: the WASM binary is not loaded until `initWasm()` is awaited
- Fails gracefully: if `@drs/wasm` is not installed, a clear error is thrown
- Provides a synchronous getter `getWasmModule()` after init completes

---

## Module Structure

| File | Responsibility |
|---|---|
| `sdk/types.ts` | All DRS interfaces (mirrors Rust/Go types exactly) |
| `sdk/issue.ts` | `issueRootDelegation`, `issueSubDelegation`, `issueInvocation`, `buildJwt` |
| `sdk/bundle.ts` | `buildBundle`, `serialiseBundle`, `parseBundle` |
| `sdk/policy.ts` | `checkPolicyAttenuation`, `translatePolicy` |
| `sdk/base64url.ts` | Base64url encode/decode (RFC 4648 §5) |
| `sdk/translate.ts` | Re-exports `translatePolicy` for CLI use |
| `verify/client.ts` | `VerifyClient` — HTTP client for drs-verify |
| `wasm/loader.ts` | `initWasm`, `getWasmModule`, `isWasmReady` |
| `cli/index.ts` | `drs` CLI entrypoint |
| `cli/commands/*.ts` | One command per file: verify, policy, translate, audit, keygen |

---

## Build and Test

```sh
pnpm install
pnpm test          # vitest run
pnpm typecheck     # tsc --noEmit
pnpm build         # tsc -p tsconfig.build.json
```

---

## CLI Usage

```sh
# Verify a bundle against drs-verify (uses DRS_VERIFY_URL env var)
drs verify bundle.json

# Display policy from a delegation receipt payload JSON
drs policy receipt.json

# Translate a policy JSON to plain English
drs translate policy.json

# Print full audit trail
drs audit bundle.json

# Generate a new Ed25519 keypair
drs keygen
```
