HIPsHanzo Proposals
Back to HIPs
HIP-1312FinalStandards TrackApplication

Company — The Formation Machine

Hanzo AI
Created: 2026-08-20
Requires: HIP-0026, HIP-0106, HIP-0139

HIP-1312: Company — The Formation Machine

Abstract

/v1/company brings a legal entity into existence and records who owns it: choose a structure, add founders, clear identity, pay the formation fee, generate documents, route signature, anchor the equity genesis. The implementation is hanzoai/cloud apps/company.

The capability is a guarded state machine — a closed table of stages and the edges between them (apps/company/machine.go) — plus provider seams that reach the outside world (apps/company/providers.go). HIP-0903 argues why a firm should run this way; this is the contract the surface answers to.

Motivation

Formation is a sequence where every step depends on a fact an earlier one established, and most of those facts are legal rather than technical: money must not move before identity clears, and an entity must not be reported as formed before it is.

Enumerating what a caller may do — a permission list — fails in the direction that matters here. A list has gaps, and a gap is a company incorporated without a verified person behind it. A closed edge table has none: the illegal move is not forbidden, it is absent.

Specification

The key words MUST, MUST NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as in RFC 2119.

§1 The machine

Two paths reach the terminal stage, every edge carrying a guard (apps/company/machine.go): incorporate — structure → founders → payment → documents → esign → genesis → company, guarded by structure chosen, identity verified, fee paid, documents generated, signature complete, genesis recorded; and import — structure → import → company, for an entity that already exists and brings its own cap table and documents.

The table MUST stay closed: an edge that is not listed does not exist, so no request shape, argument or ordering advances a formation past a guard. A new step is a new edge with a new guard in the table, never a condition in a handler.

§2 The addresses

Twenty-one paths, every one under /v1/company (manifest/apps.go:433, plugin/company/openapi.json): the machine's edges (/structure, /founders, /kyc, /kyc/decision, /kyc/refresh, /payment, /documents, /esign, /esign/complete, /genesis, /advance, /skip), the import pair, the fundraise trio, the platform book (/register, /register/summary, /review) and the GET|POST /v1/company root.

Twenty operations are typed. Two are declared with prose beside the route and held to that count by a test (apps/company/typed_wire_test.go): the deck upload takes a PDF as the raw request body, which has no value to name, and POST /payment answers denial with the fleet's nested error body, which a typed operation cannot emit. Both declare their bodies through openapi.Register, so neither publishes an address nobody can explain.

§3 The store, and the tenant

One SQLite file in the system namespace — company — holds each org's formation as a single row keyed by the org, at most one formation per org (apps/company/store.go:22-28). Documents, cap-table rows and signing material are NOT here: they live with dataroom, captable and kms behind the provider seams (apps/company/providers.go), and a formation row that also held them would make this capability the second owner of three other stores.

The org is principal.Org, the validated IAM owner claim (HIP-0026), on every read and write; a caller with no validated principal is refused.

Two surfaces are SuperAdmin's and cross-tenant by nature: the platform book (/register, /register/summary, /review) and the identity decision (/kyc/decision). Hanzo forms the entity, so Hanzo carries the formation identity obligation, and discharging it is the platform's own act rather than a predicate over the customer's. The two planes MUST stay orthogonal — the SuperAdmin operation writes a fact, the machine's guard reads it, neither calls the other — and a reviewer's confirmation MUST be recorded as its own distinct value, never as a provider verification. "A human confirmed this" and "a provider verified this" stay different facts to an auditor forever. Every privileged decision carries the deciding reviewer.

§4 The genesis anchor

The founding allocation — entity plus founders, ordered deterministically — is hashed to a keccak root and committed to the Hanzo L1 (chain 36963) by a KMS-signed transaction (apps/company/genesis.go). The chain is the source of truth, so a holder of the allocation recomputes the root without trusting this platform. When the RPC or the signer is unconfigured, the root MUST be returned with an honest pending status: a transaction hash is never fabricated and formation is never blocked on an unreachable chain.

§5 Price, events, emission, stage, upstream

The capability is metered: Price: cloud.Metered (plugin/company/main.go:27; spend.go:294) — the surface moves a four-figure sum, so the edge requires standing. The one charge is the one-time formation fee — 99900 cents (formationFeeCents, apps/company/providers.go:146; operator override CLOUD_COMPANY_FEE_CENTS, apps/company/company.go:290-297) — taken at POST /v1/company/payment through the charge seam onto the org's own ledger. Insufficient balance is 402 and an unreachable balance is 503; neither advances the stage, because the paid guard reads the receipt rather than the attempt (apps/company/machine.go:332-335).

It publishes no events on the bus, so a customer's webhooks (HIP-1310) receive nothing from it — provider completion arrives INBOUND at /esign/complete and /kyc/decision, it is not emitted. It emits nothing to observability beyond the request span every route gets.

The stage is beta (HIP-0139 §8): a vertical application rather than core, so an org reaches it by the company flag. The manifest row declares it (manifest/apps.go:433, Stage: Beta). It derives from no OSS upstream — the identity and filing providers are hand-written clients behind the seams (apps/company/providers.go, apps/company/filing.go).

Rationale

The alternative to the closed edge table is scopes: enumerate what each caller may invoke and check the enumeration in every handler. It costs one gap to be wrong, the gaps are invisible until exploited, and each new stage multiplies the checks that must agree. The table has one place to be right.

The alternative to the platform book is per-tenant records only, which cannot answer what the obligation actually poses: how many formations await review, and which have waited longest. That question is cross-tenant because the duty is.

Security Considerations

The wrong implementation hands an attacker one of three things. Another org's formation row is its founders' identity documents and personal data — the most sensitive record this platform holds outside secrets. A decision operation reachable by a non-SuperAdmin is laundered identity approval: a self-declared founder who then clears the guard. And an edge table with one extra entry is a company formed without payment or without a verified person behind it — a real entity, in a real jurisdiction, traceable to us. The anchor adds a fourth: a fabricated transaction hash is a false claim of public verifiability, worse than no claim, because a reader who checks the chain and finds nothing has already relied on it.

References

  • HIP-0026 — Identity and Access Management
  • HIP-0106 — Hanzo Plugin Contract
  • HIP-0139 — Capability
  • HIP-0903 — The Agentic Company — Autonomous Firms on Hanzo
  • HIP-1310 — Webhooks — Outbound Delivery

Copyright

Released under CC0 1.0 Universal Public Domain Dedication.