mirror of
https://github.com/hanzo-docs/docs.git
synced 2026-10-24 20:09:02 +00:00
docs: current-state product pages (sign/dataroom/captable) + plugin-platform architecture
Product pages — corrected to what each app actually does today:
- sign: esign.hanzo.ai (not sign.hanzo.ai); image ghcr.io/hanzoai/esign; IAM_URL;
real FieldType enum; /api/v1 (ts-rest, stable) + /api/v2 (tRPC) surfaces;
framed as the AGPLv3 open-source e-signature app it is.
- dataroom: Papermark fork; embedded SQLite default (not Postgres); drop the
fabricated LinkedIn OAuth and invented clean-REST contract; add real features
(conversations, AI Q&A, file requests, SCIM, Hanko passkeys, BoxyHQ SAML);
honest unversioned /api surface.
- captable: drop fabricated 409A history / waterfall / round-modeling and the
invented REST endpoints; document the real tRPC + Hono /api/v1 API
(OpenAPI at /v1/docs); IAM_URL; note incorporation is WIP.
Architecture section (new) — explicitly direction, not shipped:
- content/docs/architecture/{index,plugin-platform}.mdx + meta.json, wired into
the root nav after Proof of AI. Documents the consensus-backed plugin platform
(HIP-0116, Draft): plugins as the unit (cloud.Register, HIP-0105); a small
post-quantum BFT (Quasar) control plane holding the placement map + writer
leases, with the data plane reusing existing S3/ZapDB replication (HIP-0107);
5 voters + N data nodes, pinned writers, per-connection pinning, per-tenant
sharding; ZAP-native authoring (HIP-0114). Every code sample is labeled
proposed / not-yet-available; consensus-off-the-data-path is called out.
The services nav derives from @hanzo/products (gen-services-nav.ts); sign,
dataroom and captable remain under the generated "More" group until they are
added to the commerce catalog + snapshot — a registry change out of scope for a
docs-only PR.
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
---
|
||||
title: Architecture
|
||||
description: How Hanzo Cloud is built today, and the plugin-platform direction it is evolving toward.
|
||||
index: true
|
||||
---
|
||||
|
||||
# Architecture
|
||||
|
||||
This section explains how Hanzo Cloud is put together — what runs today, and where the platform is headed. We keep the two clearly separated: the product pages elsewhere in these docs describe shipped behavior, while the platform direction here is design work being ratified through the [Hanzo Improvement Proposals (HIPs)](https://hips.hanzo.ai).
|
||||
|
||||
## Today
|
||||
|
||||
Hanzo Cloud is a family of services behind one front door. A single API key at `api.hanzo.ai` reaches every service — AI inference, identity, secrets, storage, commerce, and more — grouped into ten categories: AI, Compute, Data, Network, Security, Observe, Platform, Web3, Apps, and Commerce. See [Platform & Services](/docs/services) for the full catalog.
|
||||
|
||||
Each product is its own repository and its own container image, deployed and reconciled independently. Some products run as standalone applications on their own domains — for example [Sign](/docs/services/sign) (`esign.hanzo.ai`), [Dataroom](/docs/services/dataroom) (`dataroom.hanzo.ai`), and [Cap Table](/docs/services/captable) (`captable.hanzo.ai`). They authenticate through Hanzo IAM, but each runs as its own application rather than inside a single shared runtime.
|
||||
|
||||
## Direction
|
||||
|
||||
The platform is converging on one model for running these services: a **consensus-backed plugin platform**, where each service is a *plugin* registered into a single cloud runtime, and a small consensus control plane decides where each plugin's writers live. This is a design direction — specified as a draft proposal, not yet a shipped runtime.
|
||||
|
||||
<Cards>
|
||||
<Card title="Consensus-Backed Plugin Platform" href="/docs/architecture/plugin-platform" description="The HIP-0116 direction: plugins as the unit, consensus over placement, ZAP-native authoring." />
|
||||
<Card title="ZAP Protocol" href="/docs/zap" description="Zero-Copy App Proto — the high-performance transport plugins default to." />
|
||||
<Card title="Hanzo Improvement Proposals" href="https://hips.hanzo.ai" description="Where platform architecture is specified and ratified." />
|
||||
</Cards>
|
||||
|
||||
<Callout type="info">
|
||||
The plugin platform is described in **HIP-0116 (Draft)**. It builds on a set of related proposals — the in-process extension runtime (HIP-0105), the unified cloud binary (HIP-0106), streaming replication (HIP-0107), and the ZAP transport (HIP-0114). Draft proposals may change; nothing on the [plugin-platform page](/docs/architecture/plugin-platform) is a shipped user feature.
|
||||
</Callout>
|
||||
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"title": "Architecture",
|
||||
"description": "How Hanzo Cloud is built today, and the plugin-platform direction it is evolving toward",
|
||||
"icon": "Blocks",
|
||||
"pages": [
|
||||
"index",
|
||||
"plugin-platform"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
---
|
||||
title: Consensus-Backed Plugin Platform
|
||||
description: The architecture direction for Hanzo Cloud — plugins as the unit of deployment, a small consensus control plane over placement, and ZAP-native authoring. Specified in HIP-0116 (Draft).
|
||||
---
|
||||
|
||||
# Consensus-Backed Plugin Platform
|
||||
|
||||
<Callout type="warn">
|
||||
This page describes a **design direction**, not a shipped feature. The runtime it describes is specified in **HIP-0116 (Draft)** and is **not yet built**. It is published so the design can be reviewed. For what runs today, see the product pages under [Platform & Services](/docs/services); this page is about where the platform is headed and why.
|
||||
</Callout>
|
||||
|
||||
Hanzo Cloud today is many services, each its own repository, image, and deployment. The direction is to run them as **plugins** inside one cloud runtime, and to let a **small consensus control plane** decide where each plugin's write side lives. The goal is that a service author writes almost none of the hard parts — placement, failover, replication, high availability — and inherits them from the platform.
|
||||
|
||||
The design rests on one principle: **consensus orders decisions, not bytes.**
|
||||
|
||||
## The unit is a plugin
|
||||
|
||||
In the proposed model (HIP-0105, *In-Process Extension Runtime Standard*), a service registers itself with a single call:
|
||||
|
||||
```go
|
||||
// Proposed API (HIP-0105) — not yet available.
|
||||
func init() {
|
||||
cloud.Register("kms", 500, mount)
|
||||
}
|
||||
```
|
||||
|
||||
A plugin is the unit the platform places and scales. The `cloud` binary loads a set of registered plugins; **nodes specialize** by running a dynamic subset of them rather than every node running everything. That makes the runtime one deployable artifact whose behavior on each node is data — the placement decision — rather than a per-service build.
|
||||
|
||||
Existing subsystems — KMS, IAM, Base, Gateway, Commerce, tasks, pubsub — are exactly the kind of thing that becomes a plugin under this model. They are **not** plugins today; this is the target.
|
||||
|
||||
## Consensus orders decisions, not bytes
|
||||
|
||||
The platform splits into two planes that are deliberately kept separate.
|
||||
|
||||
**Control plane — a small, fixed quorum.** Five voter nodes run a post-quantum BFT consensus engine (the **Quasar** engine from Lux, with a post-quantum certificate profile). Its replicated log orders only tiny metadata:
|
||||
|
||||
- cluster membership,
|
||||
- the **placement map** — which node holds the writer for each `(plugin, shard)`, and its followers,
|
||||
- **writer leases** with fencing epochs, so there is exactly one writer per shard per epoch.
|
||||
|
||||
**Data plane — reuse what exists.** The bytes do not go through consensus. The data plane reuses the existing streaming replication (HIP-0107) that already backs the platform's storage — the S3 / ZapDB log-ship. The only change is the write fence: instead of asking "do I hold a Kubernetes lease?", a writer asks "does the control plane grant this shard's lease at the current epoch?"
|
||||
|
||||
The consequence is the important part:
|
||||
|
||||
<Callout type="info">
|
||||
**Consensus sits off the data path.** If the control-plane quorum is lost, placement and failover freeze — but serving does not stop. Every current writer keeps its lease and keeps writing; readers keep reading. Losing quorum degrades **failover**, not availability. This is the Chubby / etcd shape applied to the Hanzo runtime.
|
||||
</Callout>
|
||||
|
||||
## Scaling to N nodes
|
||||
|
||||
The two planes scale independently:
|
||||
|
||||
- **5 voters** run the control plane. The quorum is small and fixed, so adding capacity never slows consensus.
|
||||
- **N data nodes** host plugin shards and each follow a read-only copy of the placement map. `N` grows without bound.
|
||||
|
||||
Within that topology:
|
||||
|
||||
- **Pinned writers** — each shard has one writer node, assigned by the placement map, so writes have a single owner and never conflict.
|
||||
- **Per-connection pinning** — a client's connection is routed to the node that currently owns the shard it is talking to, so reads and writes land on the right replica.
|
||||
- **Per-tenant sharding** — the write side can be split by tenant, down to a `(plugin, org)` shard, so a single busy organization gets its own writer. Fine per-tenant sharding is a **later stage** of the proposal; the earlier stages run one writer per plugin.
|
||||
|
||||
## ZAP-native, easy plugin authoring
|
||||
|
||||
The payoff is the developer experience. Under HIP-0105 and HIP-0114, a plugin author implements one small interface and calls `cloud.Register`. In return the platform supplies placement, per-tenant scale, replication, per-connection pinning, and high availability — none of which the author writes.
|
||||
|
||||
```go
|
||||
// Proposed authoring model (HIP-0105 / HIP-0116) — illustrative, not yet available.
|
||||
// The author writes the handler; the platform supplies placement + replication + HA.
|
||||
func mount(deps cloud.Deps) http.Handler {
|
||||
db := deps.OpenShard("kms") // the placement-assigned shard for this node
|
||||
return newHandler(db) // ...just serve requests
|
||||
}
|
||||
|
||||
func init() { cloud.Register("kms", 500, mount) }
|
||||
```
|
||||
|
||||
The default wire is **ZAP** (Zero-Copy App Proto, HIP-0114) — the same high-performance, post-quantum transport documented in the [ZAP section](/docs/zap). Every plugin registered through `cloud.Register` speaks ZAP with no extra work, so cross-plugin and inter-node calls get zero-copy performance by default rather than as an opt-in.
|
||||
|
||||
<Callout type="warn">
|
||||
The snippets above show the **proposed** shape of the API to illustrate the direction. They are not a tutorial for a runtime that exists today — there is no `cloud.Register` plugin runtime to deploy against yet. Treat them as design, pending ratification of HIP-0116.
|
||||
</Callout>
|
||||
|
||||
## Where this is specified
|
||||
|
||||
The plugin platform is defined across a set of Hanzo Improvement Proposals. Statuses are as of writing and may change — track them at [hips.hanzo.ai](https://hips.hanzo.ai) and [github.com/hanzoai/hips](https://github.com/hanzoai/hips).
|
||||
|
||||
| HIP | Title | Status |
|
||||
|-----|-------|--------|
|
||||
| HIP-0116 | Consensus-Backed Plugin-Placement Platform | Draft |
|
||||
| HIP-0105 | In-Process Extension Runtime Standard | Draft |
|
||||
| HIP-0106 | Unified Hanzo Cloud Binary | Draft |
|
||||
| HIP-0107 | Streaming Replication over VFS | Draft |
|
||||
| HIP-0112 | Cloud Infrastructure Topology Standard | Active |
|
||||
| HIP-0114 | ZAP — Inter-VM Cognitive Transport | Draft |
|
||||
|
||||
## Next Steps
|
||||
|
||||
<Cards>
|
||||
<Card title="Architecture Overview" href="/docs/architecture" description="How Hanzo Cloud is built today, and the direction it is evolving toward." />
|
||||
<Card title="ZAP Protocol" href="/docs/zap" description="The zero-copy transport plugins default to." />
|
||||
<Card title="Platform & Services" href="/docs/services" description="The services that run today, behind one api.hanzo.ai." />
|
||||
</Cards>
|
||||
@@ -22,6 +22,8 @@
|
||||
"commerce",
|
||||
"---Proof of AI---",
|
||||
"proof-of-ai",
|
||||
"---Architecture---",
|
||||
"architecture",
|
||||
"---Infrastructure---",
|
||||
"tasks",
|
||||
"functions",
|
||||
|
||||
@@ -5,19 +5,24 @@ description: Equity management and cap table platform
|
||||
|
||||
# Hanzo Cap Table
|
||||
|
||||
Hanzo Cap Table is an equity management platform for startups and growth-stage companies. Manage share classes, stock options, SAFEs, convertible notes, and equity plans with full audit trails and built-in e-signing.
|
||||
Hanzo Cap Table is an open-source equity-management platform for startups and growth-stage companies — a self-hostable alternative to Carta, Pulley, and AngelList. Manage share classes, stock options, SAFEs, and convertible notes; run fundraising rounds; share documents in a data room; and collect signatures — all with a full audit trail. It runs as a standalone Next.js application at `captable.hanzo.ai` and signs in through Hanzo IAM.
|
||||
|
||||
> The equity, fundraising, document, data-room, e-signing, and investor-update workflows are production features today. Company incorporation is still under active development and is marked as a work in progress inside the app.
|
||||
|
||||
## Features
|
||||
|
||||
- **Share Classes**: Common, preferred, and custom share classes
|
||||
- **Stock Options**: ISO and NSO option grants with vesting schedules
|
||||
- **SAFEs**: Y Combinator SAFE management with conversion modeling
|
||||
- **Convertible Notes**: Track notes with interest, caps, and discounts
|
||||
- **Share Classes**: Common and preferred classes with customizable terms
|
||||
- **Securities**: Shares, stock options (ISO / NSO / RSU), SAFEs, and convertible notes
|
||||
- **SAFEs**: The six standard Y Combinator SAFE templates plus custom terms — valuation cap, discount, MFN, and pro-rata rights
|
||||
- **Convertible Notes**: CCD, OCD, and NOTE instruments with interest accrual
|
||||
- **Equity Plans**: Option pools and equity incentive plans
|
||||
- **Vesting Schedules**: Cliff, linear, and custom vesting
|
||||
- **409A Valuations**: Track fair market value history
|
||||
- **E-Signing**: Built-in document signing for equity grants
|
||||
- **Data Rooms**: Integrated document management
|
||||
- **Vesting Schedules**: Cliff plus multi-year vesting on shares and option grants
|
||||
- **Stakeholders**: Individuals and institutions with relationship types (founder, employee, investor, advisor, and more)
|
||||
- **Fundraising**: Track investments, issue securities, and manage round participants
|
||||
- **Documents & Data Rooms**: Upload to S3-compatible storage and share through access-controlled data rooms
|
||||
- **E-Signing**: Built-in PDF signing workflows for equity grants and agreements
|
||||
- **Investor Updates**: Rich-text updates with public/private visibility and recipient tracking
|
||||
- **Roles & Permissions**: Role-based access control with a full activity audit log
|
||||
- **Hanzo IAM SSO**: Single sign-on via Hanzo identity
|
||||
|
||||
## Endpoints
|
||||
@@ -25,12 +30,14 @@ Hanzo Cap Table is an equity management platform for startups and growth-stage c
|
||||
| Environment | URL |
|
||||
|-------------|-----|
|
||||
| Production | `https://captable.hanzo.ai` |
|
||||
| REST API | `https://captable.hanzo.ai/api/v1` |
|
||||
| API reference | `https://captable.hanzo.ai/v1/docs` |
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------+
|
||||
| HANZO CAP TABLE |
|
||||
| HANZO CAP TABLE |
|
||||
+---------------------------------------------------------------+
|
||||
| |
|
||||
| +-----------------------+ +-------------------------------+ |
|
||||
@@ -41,106 +48,34 @@ Hanzo Cap Table is an equity management platform for startups and growth-stage c
|
||||
| +-----------------------+ +-------------------------------+ |
|
||||
| |
|
||||
| +-----------------------+ +-------------------------------+ |
|
||||
| | Instruments | | Compliance | |
|
||||
| | Instruments | | Governance | |
|
||||
| | +------+ +-------+ | | +--------+ +-------------+ | |
|
||||
| | | SAFE | | Notes | | | | 409A | | Audit Log | | |
|
||||
| | | SAFE | | Notes | | | | RBAC | | Audit Log | | |
|
||||
| | +------+ +-------+ | | +--------+ +-------------+ | |
|
||||
| +-----------------------+ +-------------------------------+ |
|
||||
| |
|
||||
+---------------------------------------------------------------+
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
## How It Works
|
||||
|
||||
### 1. Create a Company
|
||||
Cap-table operations are carried out in the dashboard and recorded in the audit log.
|
||||
|
||||
Set up your company profile with incorporation details:
|
||||
### 1. Set Up the Company
|
||||
|
||||
```typescript
|
||||
const company = await fetch('https://captable.hanzo.ai/api/company', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiToken}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: 'Acme Corp',
|
||||
incorporationDate: '2024-01-15',
|
||||
incorporationState: 'DE',
|
||||
incorporationCountry: 'US'
|
||||
})
|
||||
})
|
||||
```
|
||||
Create the company profile with its incorporation details, then invite team members and assign roles.
|
||||
|
||||
### 2. Create Share Classes
|
||||
### 2. Define Share Classes
|
||||
|
||||
```typescript
|
||||
// Common stock
|
||||
await fetch('https://captable.hanzo.ai/api/share-classes', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: JSON.stringify({
|
||||
name: 'Common Stock',
|
||||
classType: 'COMMON',
|
||||
authorizedShares: 10000000,
|
||||
parValue: 0.0001,
|
||||
votesPerShare: 1
|
||||
})
|
||||
})
|
||||
Add common and preferred share classes — each with authorized shares, par value, and voting rights, plus liquidation preferences and conversion terms for preferred classes.
|
||||
|
||||
// Preferred stock
|
||||
await fetch('https://captable.hanzo.ai/api/share-classes', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: JSON.stringify({
|
||||
name: 'Series Seed Preferred',
|
||||
classType: 'PREFERRED',
|
||||
authorizedShares: 2000000,
|
||||
parValue: 0.0001,
|
||||
liquidationPreference: 1.0,
|
||||
conversionRatio: 1.0
|
||||
})
|
||||
})
|
||||
```
|
||||
### 3. Issue Securities
|
||||
|
||||
### 3. Issue Shares
|
||||
Issue shares and grant options (ISO / NSO / RSU) to stakeholders, attaching vesting schedules where applicable.
|
||||
|
||||
```typescript
|
||||
await fetch('https://captable.hanzo.ai/api/shares/issue', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: JSON.stringify({
|
||||
stakeholderId: 'founder-1',
|
||||
shareClassId: 'common-stock-id',
|
||||
quantity: 5000000,
|
||||
pricePerShare: 0.0001,
|
||||
vestingSchedule: {
|
||||
type: 'CLIFF_LINEAR',
|
||||
cliffMonths: 12,
|
||||
totalMonths: 48,
|
||||
startDate: '2024-01-15'
|
||||
}
|
||||
})
|
||||
})
|
||||
```
|
||||
### 4. Run Fundraising
|
||||
|
||||
### 4. Create a SAFE
|
||||
|
||||
```typescript
|
||||
await fetch('https://captable.hanzo.ai/api/safes', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: JSON.stringify({
|
||||
investorId: 'investor-1',
|
||||
investmentAmount: 500000,
|
||||
valuationCap: 10000000,
|
||||
discount: 0.20,
|
||||
proRata: true,
|
||||
mfn: true,
|
||||
safeType: 'POST_MONEY'
|
||||
})
|
||||
})
|
||||
```
|
||||
Model SAFEs and convertible notes — valuation caps, discounts, MFN, and pro-rata rights — and track investments through the round.
|
||||
|
||||
## Securities Types
|
||||
|
||||
@@ -151,56 +86,38 @@ await fetch('https://captable.hanzo.ai/api/safes', {
|
||||
| Stock Options (ISO) | Incentive stock options (tax-advantaged) |
|
||||
| Stock Options (NSO) | Non-qualified stock options |
|
||||
| RSUs | Restricted stock units |
|
||||
| SAFEs | Simple Agreement for Future Equity |
|
||||
| Convertible Notes | Debt instruments convertible to equity |
|
||||
| Warrants | Right to purchase shares at a set price |
|
||||
| SAFEs | Simple Agreement for Future Equity (six YC templates + custom) |
|
||||
| Convertible Notes | Debt instruments convertible to equity (CCD / OCD / NOTE) |
|
||||
|
||||
## Vesting Schedules
|
||||
## Vesting
|
||||
|
||||
| Schedule | Description |
|
||||
|----------|-------------|
|
||||
| `CLIFF_LINEAR` | Cliff period then monthly vesting |
|
||||
| `LINEAR` | Equal monthly vesting from start |
|
||||
| `BACK_WEIGHTED` | Accelerating vesting over time |
|
||||
| `CUSTOM` | Custom milestone-based vesting |
|
||||
| `IMMEDIATE` | Fully vested on grant |
|
||||
|
||||
### Standard 4-Year with 1-Year Cliff
|
||||
Shares and option grants support a cliff followed by multi-year vesting. The most common schedule is four-year vesting with a one-year cliff:
|
||||
|
||||
```
|
||||
Year 1: 0% → 25% (cliff)
|
||||
Year 2: 25% → 50% (monthly)
|
||||
Year 3: 50% → 75% (monthly)
|
||||
Year 4: 75% → 100% (monthly)
|
||||
Year 2: 25% → 50%
|
||||
Year 3: 50% → 75%
|
||||
Year 4: 75% → 100%
|
||||
```
|
||||
|
||||
## Cap Table Reports
|
||||
## Ownership View
|
||||
|
||||
### Ownership Summary
|
||||
|
||||
View current ownership percentages across all stakeholders, including fully-diluted calculations.
|
||||
|
||||
### Waterfall Analysis
|
||||
|
||||
Model liquidation scenarios to understand payout distributions at various exit valuations.
|
||||
|
||||
### Round Modeling
|
||||
|
||||
Project dilution and ownership changes for future financing rounds.
|
||||
The cap table shows current ownership across all stakeholders, including fully-diluted figures that account for the option pool and outstanding convertible instruments.
|
||||
|
||||
## Authentication
|
||||
|
||||
Hanzo Cap Table supports multiple authentication methods:
|
||||
Hanzo Cap Table signs users in through Hanzo IAM and supports:
|
||||
|
||||
- **Hanzo IAM**: SSO via `https://hanzo.id` (recommended)
|
||||
- **Google OAuth**: Sign in with Google
|
||||
- **Hanzo IAM**: SSO via `https://hanzo.id` (required for production)
|
||||
- **Email & Password**: Native NextAuth accounts
|
||||
- **Passkeys**: WebAuthn/FIDO2 authentication
|
||||
- **Google OAuth**: Optional legacy provider
|
||||
|
||||
### IAM Integration
|
||||
|
||||
```bash
|
||||
# Environment variables
|
||||
IAM_ENDPOINT=https://hanzo.id
|
||||
IAM_URL=https://hanzo.id
|
||||
IAM_CLIENT_ID=app-captable
|
||||
IAM_CLIENT_SECRET=<from-kms>
|
||||
```
|
||||
@@ -215,7 +132,7 @@ docker run -d \
|
||||
-p 3000:3000 \
|
||||
-e DATABASE_URL=postgres://... \
|
||||
-e NEXTAUTH_URL=https://captable.yourdomain.com \
|
||||
-e IAM_ENDPOINT=https://hanzo.id \
|
||||
-e IAM_URL=https://hanzo.id \
|
||||
-e IAM_CLIENT_ID=app-captable \
|
||||
ghcr.io/hanzoai/captable:latest
|
||||
```
|
||||
@@ -227,38 +144,18 @@ docker run -d \
|
||||
| `DATABASE_URL` | PostgreSQL connection string |
|
||||
| `NEXTAUTH_URL` | Public URL of the application |
|
||||
| `NEXTAUTH_SECRET` | NextAuth encryption secret |
|
||||
| `IAM_ENDPOINT` | Hanzo IAM server URL |
|
||||
| `IAM_URL` | Hanzo IAM server URL |
|
||||
| `IAM_CLIENT_ID` | IAM application client ID |
|
||||
| `IAM_CLIENT_SECRET` | IAM application client secret |
|
||||
| `S3_*` | S3-compatible object storage credentials (S3, MinIO, or R2) |
|
||||
| `SMTP_HOST` | Email server host |
|
||||
| `STRIPE_SECRET_KEY` | Stripe billing key |
|
||||
|
||||
## API Reference
|
||||
## API
|
||||
|
||||
### Share Classes
|
||||
Hanzo Cap Table is built on **tRPC** for type-safe internal calls, with a **REST API** exposed under `/api/v1` (built on Hono) and an interactive **OpenAPI reference at `/v1/docs`**. Programmatic access uses scoped API tokens; token types include API access, signature, data-room, and investor-update tokens.
|
||||
|
||||
- `POST /api/share-classes` - Create share class
|
||||
- `GET /api/share-classes` - List share classes
|
||||
- `PATCH /api/share-classes/:id` - Update share class
|
||||
|
||||
### Stakeholders
|
||||
|
||||
- `POST /api/stakeholders` - Add stakeholder
|
||||
- `GET /api/stakeholders` - List stakeholders
|
||||
- `GET /api/stakeholders/:id` - Get stakeholder details
|
||||
|
||||
### Securities
|
||||
|
||||
- `POST /api/shares/issue` - Issue shares
|
||||
- `POST /api/options/grant` - Grant options
|
||||
- `POST /api/safes` - Create SAFE
|
||||
- `POST /api/convertible-notes` - Create convertible note
|
||||
|
||||
### Reports
|
||||
|
||||
- `GET /api/reports/captable` - Current cap table
|
||||
- `GET /api/reports/waterfall` - Waterfall analysis
|
||||
- `GET /api/reports/409a` - 409A valuation history
|
||||
The API covers the same resources as the dashboard — companies and members, stakeholders, share classes and equity plans, securities (shares, options, SAFEs, convertible notes), documents and data rooms, and investor updates. See `/v1/docs` on your instance for the exact request and response shapes.
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
@@ -5,16 +5,23 @@ description: Secure document sharing with analytics and access controls
|
||||
|
||||
# Hanzo Dataroom
|
||||
|
||||
Hanzo Dataroom is a secure document sharing platform with real-time analytics, granular access controls, and custom branding. Share pitch decks, fundraising materials, legal documents, and more with full visibility into how recipients engage.
|
||||
Hanzo Dataroom is an open-source secure document-sharing platform — a self-hostable fork of Papermark (AGPLv3) — with real-time analytics, granular access controls, and custom branding. Share pitch decks, fundraising materials, and legal documents through controlled links, and organize due-diligence material into structured data rooms with full visibility into how recipients engage. It runs as a standalone Next.js application at `dataroom.hanzo.ai` and signs in through Hanzo IAM.
|
||||
|
||||
## Features
|
||||
|
||||
- **Secure Sharing**: Password protection, email verification, NDA agreements
|
||||
- **Real-Time Analytics**: Page-by-page view tracking, time spent, completion rates
|
||||
- **Custom Branding**: Per-team logos, colors, and custom domains
|
||||
- **Data Rooms**: Organized folder structures for due diligence and fundraising
|
||||
- **Access Controls**: Expiration dates, download restrictions, watermarking
|
||||
- **SAML SSO**: Enterprise single sign-on via BoxyHQ Jackson
|
||||
- **Shareable Links**: Per-link expiration, password protection, email verification, and allow/deny lists
|
||||
- **Watermarking**: Dynamic watermarks stamped with viewer information
|
||||
- **Screenshot Protection**: Discourage capture of sensitive material
|
||||
- **Custom Domains & Branding**: Per-team logos and colors, custom domains, and custom link metatags
|
||||
- **Data Rooms**: Multi-document collections with folders, viewer groups, and granular permissions
|
||||
- **Real-Time Analytics**: Page-by-page view tracking, time spent, downloads, and per-page reactions
|
||||
- **Conversations**: Comment threads on documents and data rooms
|
||||
- **AI Q&A**: Chat over documents and data rooms (optional; requires a model-provider key)
|
||||
- **File Requests**: Collect document uploads from visitors through a link
|
||||
- **Link Presets & Tags**: Reusable link configurations and labels across links, documents, and data rooms
|
||||
- **NDA & Agreements**: Require acceptance before viewing
|
||||
- **Enterprise SSO**: SAML via BoxyHQ Jackson, plus SCIM directory sync
|
||||
- **Passkeys**: WebAuthn authentication via Hanko
|
||||
- **Hanzo IAM SSO**: Single sign-on via Hanzo identity
|
||||
|
||||
## Endpoints
|
||||
@@ -28,7 +35,7 @@ Hanzo Dataroom is a secure document sharing platform with real-time analytics, g
|
||||
|
||||
```
|
||||
+---------------------------------------------------------------+
|
||||
| HANZO DATAROOM |
|
||||
| HANZO DATAROOM |
|
||||
+---------------------------------------------------------------+
|
||||
| |
|
||||
| +-----------------------+ +-------------------------------+ |
|
||||
@@ -48,113 +55,38 @@ Hanzo Dataroom is a secure document sharing platform with real-time analytics, g
|
||||
+---------------------------------------------------------------+
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
## How It Works
|
||||
|
||||
The full workflow runs in the dashboard.
|
||||
|
||||
### 1. Upload a Document
|
||||
|
||||
```typescript
|
||||
const formData = new FormData()
|
||||
formData.append('file', pdfFile)
|
||||
|
||||
const response = await fetch('https://dataroom.hanzo.ai/api/documents', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: formData
|
||||
})
|
||||
|
||||
const { id: documentId } = await response.json()
|
||||
```
|
||||
Upload a PDF (or other supported file) to your team's library. Uploads go to S3-compatible object storage or Vercel Blob, depending on the configured transport, with resumable upload support.
|
||||
|
||||
### 2. Create a Sharing Link
|
||||
|
||||
```typescript
|
||||
const link = await fetch('https://dataroom.hanzo.ai/api/links', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiToken}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
documentId,
|
||||
name: 'Investor Deck - Series A',
|
||||
password: 'optional-password',
|
||||
expiresAt: '2026-04-01T00:00:00Z',
|
||||
emailProtected: true,
|
||||
allowDownload: false,
|
||||
enableWatermark: true
|
||||
})
|
||||
})
|
||||
Generate a link and attach controls — a name, optional password, expiration date, email verification, allow/deny lists, download permission, and watermarking. Share the resulting `/view/...` URL with recipients.
|
||||
|
||||
// Share this URL with recipients
|
||||
console.log(link.url) // https://dataroom.hanzo.ai/view/abc123
|
||||
```
|
||||
### 3. Track Engagement
|
||||
|
||||
### 3. View Analytics
|
||||
|
||||
```typescript
|
||||
const analytics = await fetch(
|
||||
`https://dataroom.hanzo.ai/api/links/${linkId}/analytics`,
|
||||
{ headers: { 'Authorization': `Bearer ${apiToken}` } }
|
||||
).then(r => r.json())
|
||||
|
||||
// Per-viewer engagement data
|
||||
analytics.views.forEach(view => {
|
||||
console.log(`${view.email}: ${view.totalDuration}s, ${view.completionRate}%`)
|
||||
view.pages.forEach(page => {
|
||||
console.log(` Page ${page.number}: ${page.duration}s`)
|
||||
})
|
||||
})
|
||||
```
|
||||
Watch views arrive in real time: who opened the link, how long they spent on each page, which pages they revisited, and what they downloaded.
|
||||
|
||||
## Data Rooms
|
||||
|
||||
Organize documents into structured data rooms for due diligence, fundraising, or any multi-document workflow.
|
||||
|
||||
### Create a Data Room
|
||||
|
||||
```typescript
|
||||
const dataroom = await fetch('https://dataroom.hanzo.ai/api/datarooms', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiToken}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
name: 'Series A Due Diligence',
|
||||
folders: [
|
||||
{ name: 'Financials' },
|
||||
{ name: 'Legal' },
|
||||
{ name: 'Product' },
|
||||
{ name: 'Team' }
|
||||
]
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
### Add Documents to Folders
|
||||
|
||||
```typescript
|
||||
await fetch(`https://dataroom.hanzo.ai/api/datarooms/${dataroomId}/documents`, {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: JSON.stringify({
|
||||
documentId,
|
||||
folderId: 'financials-folder-id'
|
||||
})
|
||||
})
|
||||
```
|
||||
Organize documents into structured data rooms for due diligence, fundraising, or any multi-document workflow. Each data room supports nested folders, viewer groups, and permission groups so different recipients see different subsets, with an optional introduction page and per-room change notifications.
|
||||
|
||||
## Access Controls
|
||||
|
||||
| Feature | Description |
|
||||
|---------|-------------|
|
||||
| Password Protection | Require password to view |
|
||||
| Email Verification | Require verified email |
|
||||
| NDA Agreement | Accept NDA before viewing |
|
||||
| Password Protection | Require a password to view |
|
||||
| Email Verification | Require a verified email |
|
||||
| NDA Agreement | Accept an NDA before viewing |
|
||||
| Expiration Date | Auto-expire links |
|
||||
| Download Restriction | Prevent PDF downloads |
|
||||
| Download Restriction | Prevent file downloads |
|
||||
| Watermarking | Dynamic watermarks with viewer info |
|
||||
| Allow List | Restrict to specific email domains |
|
||||
| Screenshot Protection | Discourage screen capture |
|
||||
| Allow / Deny Lists | Restrict to (or block) specific emails or domains |
|
||||
|
||||
## Analytics
|
||||
|
||||
@@ -174,40 +106,41 @@ Track engagement at the page level to understand which sections resonate:
|
||||
|
||||
- Time spent per page
|
||||
- Page revisits
|
||||
- Scroll depth
|
||||
- Download attempts
|
||||
- Per-page reactions
|
||||
- Download activity
|
||||
|
||||
## Authentication
|
||||
|
||||
Hanzo Dataroom supports multiple authentication methods:
|
||||
Hanzo Dataroom signs users in through Hanzo IAM and supports:
|
||||
|
||||
- **Hanzo IAM**: SSO via `https://hanzo.id` (recommended)
|
||||
- **Google OAuth**: Sign in with Google
|
||||
- **LinkedIn OAuth**: Sign in with LinkedIn
|
||||
- **Hanzo IAM**: SSO via `https://hanzo.id` (default, recommended)
|
||||
- **Email Magic Link**: Passwordless email login
|
||||
- **Passkeys**: WebAuthn/FIDO2 authentication
|
||||
- **SAML SSO**: Enterprise SSO via BoxyHQ Jackson
|
||||
- **Passkeys**: WebAuthn/FIDO2 authentication via Hanko
|
||||
- **SAML SSO**: Enterprise SSO via BoxyHQ Jackson, with SCIM directory sync
|
||||
- **Google OAuth**: Optional legacy provider
|
||||
|
||||
### IAM Integration
|
||||
|
||||
```bash
|
||||
# Environment variables
|
||||
IAM_ENDPOINT=https://hanzo.id
|
||||
IAM_URL=https://hanzo.id
|
||||
IAM_CLIENT_ID=app-dataroom
|
||||
IAM_CLIENT_SECRET=<from-kms>
|
||||
```
|
||||
|
||||
## Self-Hosting
|
||||
|
||||
Hanzo Dataroom ships as a Next.js standalone application with an embedded SQLite database by default (single-replica), so a basic deployment needs only a persistent volume and object storage.
|
||||
|
||||
### Docker
|
||||
|
||||
```bash
|
||||
docker run -d \
|
||||
--name hanzo-dataroom \
|
||||
-p 3000:3000 \
|
||||
-e DATABASE_URL=postgres://... \
|
||||
-v dataroom-data:/app/data \
|
||||
-e NEXTAUTH_URL=https://dataroom.yourdomain.com \
|
||||
-e IAM_ENDPOINT=https://hanzo.id \
|
||||
-e IAM_URL=https://hanzo.id \
|
||||
-e IAM_CLIENT_ID=app-dataroom \
|
||||
ghcr.io/hanzoai/dataroom:latest
|
||||
```
|
||||
@@ -216,40 +149,26 @@ docker run -d \
|
||||
|
||||
| Variable | Description |
|
||||
|----------|-------------|
|
||||
| `DATABASE_URL` | PostgreSQL connection string |
|
||||
| `DATABASE_URL` | Database connection (embedded SQLite by default) |
|
||||
| `NEXTAUTH_URL` | Public URL of the application |
|
||||
| `NEXTAUTH_SECRET` | NextAuth encryption secret |
|
||||
| `IAM_ENDPOINT` | Hanzo IAM server URL |
|
||||
| `IAM_URL` | Hanzo IAM server URL |
|
||||
| `IAM_CLIENT_ID` | IAM application client ID |
|
||||
| `IAM_CLIENT_SECRET` | IAM application client secret |
|
||||
| `NEXT_PUBLIC_BASE_URL` | Public base URL |
|
||||
| `NEXT_PUBLIC_UPLOAD_TRANSPORT` | Storage backend — `s3` or `vercel` |
|
||||
| `S3_*` | S3-compatible object storage credentials |
|
||||
| `SMTP_HOST` | Email server host |
|
||||
| `STRIPE_SECRET_KEY` | Stripe billing key |
|
||||
|
||||
## API Reference
|
||||
## Integrations & API
|
||||
|
||||
### Documents
|
||||
Hanzo Dataroom is primarily a dashboard-driven product: documents are uploaded, links are created, and analytics are viewed in the app. Programmatic surfaces include:
|
||||
|
||||
- `POST /api/documents` - Upload document
|
||||
- `GET /api/documents` - List documents
|
||||
- `GET /api/documents/:id` - Get document
|
||||
- `DELETE /api/documents/:id` - Delete document
|
||||
- **Next.js API routes** under `/api` (unversioned) — links, views, teams, verification, and file handling used by the app and its share pages.
|
||||
- **SAML SSO & SCIM** for enterprise identity and directory sync.
|
||||
- **Incoming webhooks** and **Slack notifications** for view and download events.
|
||||
- **AI Q&A** endpoints for chat over documents and data rooms.
|
||||
|
||||
### Links
|
||||
|
||||
- `POST /api/links` - Create sharing link
|
||||
- `GET /api/links` - List links
|
||||
- `GET /api/links/:id` - Get link details
|
||||
- `GET /api/links/:id/analytics` - Get link analytics
|
||||
- `PATCH /api/links/:id` - Update link settings
|
||||
- `DELETE /api/links/:id` - Delete link
|
||||
|
||||
### Data Rooms
|
||||
|
||||
- `POST /api/datarooms` - Create data room
|
||||
- `GET /api/datarooms` - List data rooms
|
||||
- `POST /api/datarooms/:id/documents` - Add document
|
||||
- `DELETE /api/datarooms/:id` - Delete data room
|
||||
Refer to your instance and the self-hosting configuration for the exact route set.
|
||||
|
||||
## Next Steps
|
||||
|
||||
|
||||
@@ -5,15 +5,21 @@ description: Document signing and e-signature platform
|
||||
|
||||
# Hanzo Sign
|
||||
|
||||
Hanzo Sign is a document signing platform for creating, sending, and managing legally binding electronic signatures. Built for teams that need secure, compliant e-signatures integrated with the Hanzo ecosystem.
|
||||
Hanzo Sign (also called Hanzo eSign) is an open-source document signing platform — an AGPLv3 alternative to DocuSign — for creating, sending, and managing legally binding electronic signatures. It runs as a standalone Next.js/React Router application at `esign.hanzo.ai`, integrates with Hanzo IAM for SSO, and can be self-hosted.
|
||||
|
||||
Documents are signed cryptographically: the completed PDF is sealed with a signing certificate (a P12 certificate or Google Cloud HSM key), and every action is captured in an audit trail.
|
||||
|
||||
## Features
|
||||
|
||||
- **PDF Signing**: Upload and sign PDF documents with legally binding e-signatures
|
||||
- **Templates**: Create reusable document templates with pre-defined signing fields
|
||||
- **Signing Fields**: Text, signature, initials, date, checkbox, dropdown, and more
|
||||
- **Teams & Organizations**: Multi-tenant workspace management
|
||||
- **Webhooks**: Real-time notifications for signing events
|
||||
- **PDF Signing**: Upload and sign PDF documents with legally binding, cryptographically sealed signatures
|
||||
- **Envelopes**: Group multiple documents and attachments into a single signing transaction
|
||||
- **Templates**: Create reusable document templates with pre-defined fields and bulk send
|
||||
- **Signing Fields**: Signature, initials, name, email, date, text, number, radio, checkbox, and dropdown fields
|
||||
- **Recipients & Signing Order**: Assign roles (signer, CC, viewer) and sequential signing workflows
|
||||
- **Direct Links**: Tokenized public signing links, no account required for signers
|
||||
- **Folders & Audit Trail**: Organize documents; every action recorded for compliance
|
||||
- **Teams & Organizations**: Multi-tenant workspaces with role-based access and invites
|
||||
- **Webhooks**: Real-time notifications for document lifecycle events
|
||||
- **Per-Org OIDC**: Organization-scoped SSO portals
|
||||
- **Hanzo IAM SSO**: Single sign-on via Hanzo identity
|
||||
|
||||
@@ -21,8 +27,9 @@ Hanzo Sign is a document signing platform for creating, sending, and managing le
|
||||
|
||||
| Environment | URL |
|
||||
|-------------|-----|
|
||||
| Production | `https://sign.hanzo.ai` |
|
||||
| API | `https://sign.hanzo.ai/api/v1` |
|
||||
| Production | `https://esign.hanzo.ai` |
|
||||
| API (stable) | `https://eesign.hanzo.ai/api/v1` |
|
||||
| API (v2, tRPC) | `https://esign.hanzo.ai/api/v2` |
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -55,7 +62,7 @@ Hanzo Sign is a document signing platform for creating, sending, and managing le
|
||||
Upload a PDF and add recipients:
|
||||
|
||||
```typescript
|
||||
const response = await fetch('https://sign.hanzo.ai/api/v1/documents', {
|
||||
const response = await fetch('https://esign.hanzo.ai/api/v1/documents', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${apiToken}`,
|
||||
@@ -74,7 +81,7 @@ const response = await fetch('https://sign.hanzo.ai/api/v1/documents', {
|
||||
### 2. Add Signing Fields
|
||||
|
||||
```typescript
|
||||
await fetch(`https://sign.hanzo.ai/api/v1/documents/${docId}/fields`, {
|
||||
await fetch(`https://esign.hanzo.ai/api/v1/documents/${docId}/fields`, {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: JSON.stringify({
|
||||
@@ -90,7 +97,7 @@ await fetch(`https://sign.hanzo.ai/api/v1/documents/${docId}/fields`, {
|
||||
### 3. Send for Signing
|
||||
|
||||
```typescript
|
||||
await fetch(`https://sign.hanzo.ai/api/v1/documents/${docId}/send`, {
|
||||
await fetch(`https://esign.hanzo.ai/api/v1/documents/${docId}/send`, {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` }
|
||||
})
|
||||
@@ -101,20 +108,23 @@ await fetch(`https://sign.hanzo.ai/api/v1/documents/${docId}/send`, {
|
||||
| Type | Description |
|
||||
|------|-------------|
|
||||
| `SIGNATURE` | Electronic signature |
|
||||
| `FREE_SIGNATURE` | Free-form drawn signature |
|
||||
| `INITIALS` | Signer initials |
|
||||
| `TEXT` | Free text input |
|
||||
| `NAME` | Signer name |
|
||||
| `EMAIL` | Signer email |
|
||||
| `DATE` | Date picker |
|
||||
| `CHECKBOX` | Boolean checkbox |
|
||||
| `DROPDOWN` | Select from options |
|
||||
| `TEXT` | Free text input |
|
||||
| `NUMBER` | Numeric input |
|
||||
| `RADIO` | Radio button group |
|
||||
| `CHECKBOX` | Boolean checkbox |
|
||||
| `DROPDOWN` | Select from options |
|
||||
|
||||
## Webhooks
|
||||
|
||||
### Configure Webhook
|
||||
|
||||
```typescript
|
||||
await fetch('https://sign.hanzo.ai/api/v1/webhooks', {
|
||||
await fetch('https://esign.hanzo.ai/api/v1/webhooks', {
|
||||
method: 'POST',
|
||||
headers: { 'Authorization': `Bearer ${apiToken}` },
|
||||
body: JSON.stringify({
|
||||
@@ -145,14 +155,16 @@ Hanzo Sign supports multiple authentication methods:
|
||||
|
||||
- **Hanzo IAM**: SSO via `https://hanzo.id` (recommended)
|
||||
- **Google OAuth**: Sign in with Google
|
||||
- **Email Magic Link**: Passwordless email login
|
||||
- **Passkeys**: WebAuthn/FIDO2 authentication
|
||||
- **Microsoft OAuth**: Sign in with Microsoft / Azure AD
|
||||
- **Generic OIDC**: Any OpenID Connect provider
|
||||
- **Email & Password**: Native accounts (signup can be disabled for closed deployments)
|
||||
- **Passkeys**: WebAuthn/FIDO2 authentication, plus optional 2FA
|
||||
|
||||
### IAM Integration
|
||||
|
||||
```bash
|
||||
# Environment variables
|
||||
IAM_ENDPOINT=https://hanzo.id
|
||||
IAM_URL=https://hanzo.id
|
||||
IAM_CLIENT_ID=app-sign
|
||||
IAM_CLIENT_SECRET=<from-kms>
|
||||
```
|
||||
@@ -166,9 +178,9 @@ docker run -d \
|
||||
--name hanzo-sign \
|
||||
-p 3000:3000 \
|
||||
-e DATABASE_URL=postgres://... \
|
||||
-e IAM_ENDPOINT=https://hanzo.id \
|
||||
-e IAM_URL=https://hanzo.id \
|
||||
-e IAM_CLIENT_ID=app-sign \
|
||||
ghcr.io/hanzoai/sign:latest
|
||||
ghcr.io/hanzoai/esign:latest
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
@@ -177,7 +189,7 @@ docker run -d \
|
||||
|----------|-------------|
|
||||
| `DATABASE_URL` | PostgreSQL connection string |
|
||||
| `NEXT_PUBLIC_WEBAPP_URL` | Public URL of the application |
|
||||
| `IAM_ENDPOINT` | Hanzo IAM server URL |
|
||||
| `IAM_URL` | Hanzo IAM server URL |
|
||||
| `IAM_CLIENT_ID` | IAM application client ID |
|
||||
| `IAM_CLIENT_SECRET` | IAM application client secret |
|
||||
| `NEXT_PRIVATE_ENCRYPTION_KEY` | Document encryption key |
|
||||
@@ -187,6 +199,11 @@ docker run -d \
|
||||
|
||||
## API Reference
|
||||
|
||||
Hanzo Sign exposes two API surfaces:
|
||||
|
||||
- **`/api/v1`** — the stable REST API (contract-based), authenticated with a Bearer API token. The endpoints below are on this surface.
|
||||
- **`/api/v2`** and **`/api/v2-beta`** — the current tRPC API with an auto-generated OpenAPI schema at `/api/v2/openapi.json`. This surface is evolving and covers newer capabilities (envelopes, folders, embedding).
|
||||
|
||||
### Documents
|
||||
|
||||
- `POST /api/v1/documents` - Create document
|
||||
|
||||
Reference in New Issue
Block a user