Files
hips/HIPs/hip-1143-referral-attribution.md
zeekayandHanzo Dev 7a9dcac628 What each runtime implements of the Hanzo corpus
An audit read the code and found the proposal that specifies it. Go reaches
all 122 capability proposals and 64 of the 121 other Standards Track ones;
Rust has 35, mostly the operator and the CLI; C++ has three, because the
complete original C++ in the estate is a ZAP handler, a bot nothing specifies,
and authored kernels inside forked CUDA and Metal crates.

    | | shipped | partial | none | not assessed |
    | Go   | 146 | 33 | 1 |  80 |
    | C++  |   1 |  2 | 0 | 257 |
    | Rust |  10 | 25 | 1 | 224 |

The large "not assessed" columns are the point rather than a gap. The model and
training specs are Python, the frontend and design-system proposals are
TypeScript, and recording `none` against those would read as a search that
came up empty when the honest statement is that the runtime was never the
question. Governance, Meta and Process are not graded at all.

Six proposals are Final with nothing found in Go and are left unwritten rather
than demoted: 0065, 0089, 0098, 0103, 0521 and 0902. HIP-0521 answers itself,
its own section reading "Not yet implemented". Three of the others name a
canonical Go file in consensus/protocol/auth that nobody wrote, in a package
where the four neighbouring proposals' files all exist with tests beside them.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-05 19:18:13 -07:00

5.6 KiB

hip, title, author, type, category, capability, status, implementation-go, created, requires
hip title author type category capability status implementation-go created requires
1143 Referral — An Edge From Referrer to Referee Hanzo AI Standards Track Interface referral Final shipped 2026-08-20 HIP-0026, HIP-0106, HIP-0139

HIP-1143: Referral — An Edge From Referrer to Referee

Abstract

/v1/referral is referral ATTRIBUTION: who referred whom, and whether that referee ever became a real customer. Every org has a stable code and share link, a new org claims it at signup, and an admin sweep advances signup → qualified once the referee makes metered spend. That attribution record is the whole product — the capability, implemented in hanzoai/cloud at apps/referral, MOVES NO MONEY, and this HIP states why that absence is the design.

Motivation

A referral program needs two facts nobody else records: the edge (referrer ↔ referee, first-touch, once ever) and whether the referee genuinely used the product. Signup alone is a vanity signal; metered spend is the honest one (apps/referral/referrals.go:23-26). What is owed for a qualified referral is an affiliate PAYABLE, tracked in hanzoai/commerce and settled by wire or to a connected wallet — never minted as platform credit.

Specification

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

The store

One system-namespace SQLite file, referrals.db (sqlpool.Open, cek-encrypted, single-connection): the referral edges plus a code directory. The code itself is a deterministic base32 hash of the org id (apps/referral/referrals.go:17-18), so it never changes and never has to be stored to be reproduced; the directory row only materializes the O(1) reverse lookup.

Addresses

Four operations, all typed ops, across two audiences (apps/referral/referrals.go:117-146):

  • GET /v1/referral — the caller's code, share link and referrals. A pure read: it advances nothing.
  • POST /v1/referral/claim — record a referral from a ?ref code. Idempotent and first-touch: 201 on the first claim, 200 with created:false on replay.
  • GET /v1/admin/referrals/bonuses — SuperAdmin: every edge plus a summary.
  • POST /v1/admin/referrals/sweep — SuperAdmin: the cron path, and the ONLY path that advances a referral; one pass is bounded at 500 so a backlog drains over runs instead of wedging one request.

The two admin leaves sit under a prefix another app also serves — GET /v1/admin/referrals is the affiliates analytics board — so the plugin declares its prefixes from the manifest row (plugin/referral/main.go) rather than the /v1/<name> default, and each gate is bound to the exact path it covers, never a subtree (apps/referral/referrals.go:121-135).

Tenancy

The REFEREE is the validated caller's org, never a client field, and the referrer is resolved from the code — so a caller can only ever attach THEMSELVES to someone else's code. Self-referral is 400, an unknown code 404. Writes with no validated principal are refused ahead of the body decode (requireOrgOnWrite); the two admin leaves require SuperAdmin, fail-closed.

Money

Free, said in those words: plugin/referral/main.go declares cloud.Free, and nothing here meters, gates or debits. The one money-plane touch is a READ — "has this referee spent?" — asked through the payout plane client (apps/referral/commerce.go), and the seam is deliberately read-only: TestCommerceSeamIsReadOnly fails if it ever grows a write method, because a deposit on this interface is exactly how a GET once came to mint platform credit.

Events and telemetry

It publishes nothing to the bus, so a customer's webhooks receive nothing from it. Beyond the request span, a qualification appends one referral.qualified record to cloud's tamper-evident audit trail, best-effort (apps/referral/referrals.go:531-548) — an attestation that a referee became a customer, carrying no amount because this package issues none.

Stage

beta: the manifest row declares it (manifest/apps.go:431, Stage: Beta; HIP-0139 §8).

Upstream

Derives from none.

Rationale

The alternative — the referral system granting credit directly — is the shape every referral program starts with and the one this package was cut back from: once the capability to deposit exists on this surface, a caller eventually reaches it. Splitting attribution (here) from reward (an affiliate payable in commerce) means the worst a compromised referral path can do is mislabel an edge, not print money. Qualification living only on the admin sweep, never on a GET, is the same rule one layer down: reads report state, one bounded idempotent write advances it, and the qualified_at latch makes the transition at-most-once under concurrent sweeps.

Security Considerations

Attribution is an incentive system, so the attacker is a fraudulent referrer. The closures, each specific: the referee comes only from the validated principal, so an attacker cannot claim on a victim's behalf or attach a victim to their code; first-touch-once-ever makes claim replay inert; self-referral is refused on the resolved orgs, not on the code string; and qualification keys on metered spend read from the ledger — a signal that costs real money to forge — never on signup volume. Because no path here mints credit, the residual prize for defeating all of that is a mislabeled attribution row, which the audit trail records with both orgs named.

References

  • HIP-0026 — Identity and Access Management
  • HIP-0106 — The Hanzo Plugin Contract
  • HIP-0139 — Capability

Released under CC0 1.0 Universal Public Domain Dedication.