Documentation
¶
Overview ¶
Package captable is your cap table: stakeholders, share classes, grants, SAFEs, rounds, and who owns what.
In full: stakeholders, share classes, share certificates and transfers, option grants and equity plans, SAFEs and convertible notes, priced rounds and their investments, and the summary that totals outstanding and fully-diluted ownership from them. It runs per tenant on Base/SQLite in the unified cloud binary (HIP-0106).
WRAP, DON'T REWRITE — the read-WRITE variant. Where apps/plan + apps/pricing host a read-only @hanzo catalog in goja, captable hosts the tRPC business LOGIC (ported to a self-contained goja bundle in github.com/hanzoai/ captable) and gives it PERSISTENCE over per-tenant Base/SQLite. The bundle carries logic; the Go host carries storage. The seam between them is the REUSABLE apps/goja binding (the RW-Base goja host), which esign (#100) and dataroom (#101) reuse unchanged — this leaf is just:
captable bundle (github.com/hanzoai/captable.Bundle) + the per-tenant Schema
│
apps/goja.NewBase(...) ← injects __db/__newId/__now,
│ one SQLite file per tenant,
/v1/captable/* zip routes one transaction per request
No Prisma, no Postgres, no Next.js in this path. Every route resolves the org from the VALIDATED cloud principal (principal.Org), never a client header, and that org selects the tenant's DB file AND scopes every row.
ACTIVATION: captable is NOT staged — it mounts under the mount-all default (empty CLOUD_ENABLE), so the one binary serves /v1/captable/* from first boot. There is no standalone Captable,Inc pod to defer to (the Next.js/Prisma/Postgres app is retired by this fold — no such deployment runs in the fleet), so cloud's fresh per-tenant Base/SQLite is authoritative from the first write, with no data to migrate.
Index ¶
- Variables
- func AddStakeholders(ctx context.Context, org string, holders []StakeholderInput) (int, error)
- func EnsureShareClass(ctx context.Context, org string, in ShareClassInput) (string, error)
- func IssueShares(ctx context.Context, org string, in ShareInput) error
- func Mount(app cloud.Router, deps cloud.Deps) error
- func RecordRound(ctx context.Context, org string, in RoundInput) (string, error)
- func SetIncorporation(ctx context.Context, org, companyName, incType, country, state string) error
- func Shutdown(context.Context) error
- func StakeholderIDsByEmail(ctx context.Context, org string) (map[string]string, error)
- type RoundInput
- type ShareClassInput
- type ShareInput
- type StakeholderInput
Constants ¶
This section is empty.
Variables ¶
var ErrNotMounted = errors.New("captable: subsystem not mounted")
ErrNotMounted is returned when captable has not been mounted. A caller treats it as "cap table unavailable".
Functions ¶
func AddStakeholders ¶
AddStakeholders adds one or more stakeholders (dedup by email in the bundle) and returns how many rows were inserted.
func EnsureShareClass ¶
EnsureShareClass creates a share class and returns its id (resolved via the list route, since shareClasses.create does not echo the id). If a class with the same name already exists it returns that existing id (idempotent seed).
func IssueShares ¶
func IssueShares(ctx context.Context, org string, in ShareInput) error
IssueShares issues a share certificate to a stakeholder.
func Mount ¶
Mount wires the /v1/captable/* surface onto app per HIP-0106. Constructs the value directly (cloud.NewBase) — this subsystem keeps a package global for the Shutdown hook and opens a per-tenant goja host from deps.DataDir.
func RecordRound ¶
RecordRound records a fundraising round and returns its id.
func SetIncorporation ¶
SetIncorporation records the entity kind on the tenant's canonical company row — the cap-table-layer "org is now a company" fact. companyName is required by the bundle's company.update contract.
Types ¶
type RoundInput ¶
type RoundInput struct {
Name string `json:"name"`
RoundType string `json:"roundType"` // PRICED | SAFE | CONVERTIBLE_NOTE
TargetAmount float64 `json:"targetAmount"`
PreMoneyValuation float64 `json:"preMoneyValuation,omitempty"`
}
RoundInput mirrors the rounds.create bundle contract.
type ShareClassInput ¶
type ShareClassInput struct {
}
ShareClassInput mirrors the shareClasses.create bundle contract.
type StakeholderInput ¶
type StakeholderInput struct {
Name string `json:"name"`
Email string `json:"email"`
StakeholderType string `json:"stakeholderType"` // INDIVIDUAL | INSTITUTION
CurrentRelationship string `json:"currentRelationship"` // FOUNDER | INVESTOR | EMPLOYEE …
InstitutionName string `json:"institutionName,omitempty"`
}
StakeholderInput mirrors the stakeholders.add bundle contract.