mirror of
https://github.com/luxfi/aml.git
synced 2026-09-24 00:25:20 +00:00
The defining failure of the last review was not in a plane. It was that there were TWO wirings: cmd/amld assembled a Handler by hand and the tests assembled a different one, so the record fingerprint could be a struct field the suite exercised and no column stored — every retry a permanent 409 in production while every test passed. api.Wire is now the only assembly. It creates every collection, opens every shelf, makes every join and registers what has to run on a cadence; cmd/amld supplies only what an installation answers differently, the tests call the same function, and internal/source.NoLiteral reads cmd/amld to refuse a second copy. Handler completeness is checked by reflection, because a hand-written field list would be the third copy. A retry is not a second transaction. pkg/receipt resolves the identity of an OFFER once, at the top of ingest, before anything is read or written, and returns the prior answer byte for byte — so the ledger, the aggregates, the history, the alerts and the case plane all agree on one transaction instead of the ledger holding one record while the aggregates hold three. Two different facts under one reference is 409 and never 503. Because the answer is kept AFTER the work, a process that dies in between leaves no receipt, so every plane past it also recognises the transaction for itself: history does not append a second row, alerts keep the first judgement, and a judged transaction opens no second case. A bound over a COUNT of caller-sized values is not a bound. types.MaxIdent bounds every identifier at the door, which is what turns the counts downstream into figures in bytes; dictionary.MaxName does the same for a payload key, and dictionary.Ceiling is the product a test WEIGHS a full accumulator against. The field catalog's accumulator moves into roster, which admits and never removes, so per-tenant bounds multiply by ONE number an operator can hold against a pod. engine.Evaluator now keeps no compiled rules at all. A candidate's text arrives on the wire at /v1/aml/rules/test, so a compiled-rule table there was keyed by a string a caller wrote, sized by how many distinct ones a caller sends, with no cap and no removal, in the memory every institution's ingest runs in — an OOM from one authenticated caller, which on this deployment is every control off at once. A rule's compiled form is a value with an owner: the installed library, or one replay. Nothing shared, nothing to grow. Found here, not reported. Handler.history is the one function that materialises a whole retained history, so it now REQUIRES a *topology.Grant, and a Grant comes from Budget.Admit and nowhere else. An ungated whole-history read is something a caller has to write on purpose rather than something a new door can forget. The rule replay and the activation rate fold take the same one budget the model studies take. Reaching a bound is allowed; reaching it quietly is not. GET /v1/aml/load is the one door for "is anything of mine quietly degraded": the tenant's aggregates against its own ceiling in bytes with a grade, whether it has a behavioural model at all, the field catalog's pressure, and the process's counts of institutions held and refused. It names no other institution. Closing R1-R8 from the review plus R11, the two recurring classes, and the silent degradation the load door answers. Twenty-four mutations, twenty-four killed. Co-authored-by: Hanzo Dev <[email protected]>
124 lines
4.2 KiB
Go
124 lines
4.2 KiB
Go
// Package source reads a package's own Go source and refuses a shape.
|
|
//
|
|
// Some properties are not about what the code does today but about what it is
|
|
// still able to express. "No tenant is ever evicted to make room for another"
|
|
// is one of those: a behavioural test proves it of the code as written, and the
|
|
// same defect walks back in the moment somebody adds a map keyed by tenant with
|
|
// a cap over it. So the shape itself is refused, in the package that must not
|
|
// have it, by reading the file.
|
|
//
|
|
// It is deliberately an AST walk and not a grep. A grep for "delete(" matches a
|
|
// comment and misses a method named remove; the parser sees the declaration.
|
|
package source
|
|
|
|
import (
|
|
"go/ast"
|
|
"go/parser"
|
|
"go/token"
|
|
"testing"
|
|
)
|
|
|
|
// file parses one file of the package under test.
|
|
func file(t *testing.T, name string) (*token.FileSet, *ast.File) {
|
|
t.Helper()
|
|
fset := token.NewFileSet()
|
|
parsed, err := parser.ParseFile(fset, name, nil, parser.SkipObjectResolution)
|
|
if err != nil {
|
|
t.Fatalf("read %s: %v", name, err)
|
|
}
|
|
return fset, parsed
|
|
}
|
|
|
|
// NoTable refuses a map keyed by a string on the named type.
|
|
//
|
|
// A table held by a long-lived value grows with whatever the keys come from, and
|
|
// in this engine the keys come from callers. Two shapes, one refusal:
|
|
//
|
|
// - keyed by TENANT, it is one map of every institution's state under one cap,
|
|
// which is how one institution's traffic evicts another's — silently, with no
|
|
// error, on a control whose absence looks exactly like a clean result. Per
|
|
// tenant state belongs in roster.Roster, which admits and never removes, so
|
|
// the eviction path is not reachable rather than merely unused.
|
|
// - keyed by anything else a request carries, it is an unbounded cache: it has
|
|
// no cap at all, and the caller decides how many distinct keys exist.
|
|
//
|
|
// why states which of those the named type would be, in the caller's own words,
|
|
// so a failure names the defect rather than the rule.
|
|
func NoTable(t *testing.T, name, typeName, why string) {
|
|
t.Helper()
|
|
fset, parsed := file(t, name)
|
|
found := false
|
|
ast.Inspect(parsed, func(n ast.Node) bool {
|
|
spec, ok := n.(*ast.TypeSpec)
|
|
if !ok || spec.Name.Name != typeName {
|
|
return true
|
|
}
|
|
found = true
|
|
structure, ok := spec.Type.(*ast.StructType)
|
|
if !ok {
|
|
return false
|
|
}
|
|
for _, f := range structure.Fields.List {
|
|
m, ok := f.Type.(*ast.MapType)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if key, ok := m.Key.(*ast.Ident); ok && key.Name == "string" {
|
|
t.Errorf("%s: %s holds a map keyed by a string. %s",
|
|
fset.Position(f.Pos()), typeName, why)
|
|
}
|
|
}
|
|
return false
|
|
})
|
|
if !found {
|
|
t.Fatalf("%s declares no type %s, so this test is checking nothing", name, typeName)
|
|
}
|
|
}
|
|
|
|
// NoLiteral refuses a composite literal of pkg.Name in the named file.
|
|
//
|
|
// It is how "there is ONE way to build this" is kept true. A type with a dozen
|
|
// fields can be built by hand anywhere, and a second construction is not wrong
|
|
// on the day it is written — it is wrong on the day a field is added to one copy
|
|
// and not the other, which is a day nobody is looking.
|
|
func NoLiteral(t *testing.T, name, pkg, typeName, why string) {
|
|
t.Helper()
|
|
fset, parsed := file(t, name)
|
|
ast.Inspect(parsed, func(n ast.Node) bool {
|
|
lit, ok := n.(*ast.CompositeLit)
|
|
if !ok {
|
|
return true
|
|
}
|
|
sel, ok := lit.Type.(*ast.SelectorExpr)
|
|
if !ok || sel.Sel.Name != typeName {
|
|
return true
|
|
}
|
|
if id, ok := sel.X.(*ast.Ident); ok && id.Name == pkg {
|
|
t.Errorf("%s: %s builds a %s.%s of its own. %s",
|
|
fset.Position(lit.Pos()), name, pkg, typeName, why)
|
|
}
|
|
return true
|
|
})
|
|
}
|
|
|
|
// NoRemoval refuses any removal from a map in the named file.
|
|
//
|
|
// It is what makes roster's promise structural: a set that admits and never
|
|
// removes has no expression that could take one tenant's state, so a caller
|
|
// cannot reach one however it is composed.
|
|
func NoRemoval(t *testing.T, name string) {
|
|
t.Helper()
|
|
fset, parsed := file(t, name)
|
|
ast.Inspect(parsed, func(n ast.Node) bool {
|
|
call, ok := n.(*ast.CallExpr)
|
|
if !ok {
|
|
return true
|
|
}
|
|
if id, ok := call.Fun.(*ast.Ident); ok && id.Name == "delete" {
|
|
t.Errorf("%s: delete() — this set admits and never removes, which is the whole of what it is for",
|
|
fset.Position(call.Pos()))
|
|
}
|
|
return true
|
|
})
|
|
}
|