risk

package
v1.801.475 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 5, 2026 License: Apache-2.0 Imports: 32 Imported by: 0

Documentation

Overview

Package risk is HANZO RISK's model plane: the per-organisation feature surface and the per-organisation models trained on it.

What this app owns

/v1/risk — score, learn, state, features, search. ONE face for deciding and learning, because they are one act: the model IS the decision, and a score is only meaningful against what that organisation's model has learned.

It does NOT own /v1/ml. That prefix belongs to the model-SERVING plane (apps/ml): InferenceServices, /v1/ml/models, /v1/ml/models/{name}/predict. Serving a model somebody else trained and learning a model from an organisation's own behaviour are two different products, and putting them under one name would make /v1/ml/models mean two things at once.

It is ONE app because the model is IN-PROCESS MUTABLE STATE. If one binary learned and another scored, the two would hold different mass counters and answer one question two ways — with no error, no log and nothing to alert on. So the owner of the state is the owner of every leaf that touches it.

The moat, stated plainly

Every organisation's events already land in one columnar store through one door: product analytics, captured failures, and every priced inference. This app rolls that into a per-organisation feature surface and trains a model per organisation ON THAT ORGANISATION'S OWN DATA. Nobody who does not already operate the event surface can compute these features, and nobody who does not run the organisation's own inference can compute the spend ones.

The boundary, and why it is not merely a rule

A feature read is unspellable without a tenant: [rows] takes a [tenant], which has no exported constructor and is minted in exactly one place from the validated principal. The tenant is the LEADING BOUND predicate of every statement. The key is `<brand>/<org>`, so two brands' identically named organisations are two tenants and not one. The model geometry is seeded from that key, so two organisations do not merely have different counters — they have different trees.

Cross-organisation learning is AGGREGATE-ONLY and it is one table with no tenant column at all (baseline.go): three interpolated quantiles of one dimension over one day, published only when at least twenty-five organisations contributed. The leak is uncomputable rather than disallowed, and no model reads it — it is published for a human to compare against, never folded into a score.

What is inherited, and what had to be wired

Nothing here is free. IAM auth is global (the identity middleware mints the org from a verified bearer); the tenant reaching a TYPED op is cloud.Bridge, installed FIRST on each group; the gate and the meter are wired per op that costs compute; the scoped logger comes from cloud.NewBase; traces are ZAP-native already; health is a REAL probe this app serves itself.

Index

Constants

This section is empty.

Variables

View Source
var ErrDrainIncomplete = errors.New("risk: background work did not finish inside the shutdown window")

ErrDrainIncomplete says background work was still running when the shutdown window ran out. It is JOINED into close's error rather than replacing it: every resident model was still written down, and a fold or search cut short is a separate, NAMED fact an operator can act on instead of a silence.

Functions

func Mount

func Mount(app cloud.Router, deps cloud.Deps) error

Mount wires the model plane onto app.

It is a direct construction rather than cloud.Mount because the plane owns background work and durable state: it must be reachable from the plugin's Shutdown so a rollout snapshots every resident model instead of silently returning every tenant to warming.

func Shutdown

func Shutdown(ctx context.Context) error

Shutdown snapshots every resident model and closes the shelves.

This is not housekeeping. The binary deploys one replica at a time with the old pod stopped before the new one starts, so without this every rollout drops every warming model and the threshold it had computed — and a warming model refuses to score, which reads as "clean" to anything that does not check the refusal. A control that is off for the length of a warm period is a control that was off. The context is the shutdown WINDOW and it is honoured, not decorative: the composition root builds it with the deployment's own budget in it, so the plane has no business inventing a bound of its own — or, as it did, waiting with none.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL