Register a module only from the repository the catalogue builds it from

An agent could make a repository of its own, or fork one the mesh builds
from, commit a module.json naming sudo or mesh-host, and ask the build verb
for it: the outcome was registered under that name, and the next push made
whoever wrote it root on every node (novox/hq ADR 0266 §7, the review of
2026-10-09). The trunk rule checked the trunk of the repository built, which
was the agent's.

The take-in, which every outcome reaches whichever verb asked it, now
registers a module only from its registered repository, and a new module only
from a repository the catalogue already builds from (a merge adding one);
anything else only when the build request was kept as asked at the
controller's terminal (migration 0084). Through a verb, a build of a
repository the catalogue builds nothing from is not asked at all.
This commit is contained in:
jochen
2026-10-09 12:37:18 +02:00
parent e168b60159
commit a5e8baf6da
11 changed files with 443 additions and 15 deletions
@@ -0,0 +1,11 @@
-- A build asked at the controller's terminal says so (novox/hq ADR 0266).
--
-- A build's outcome registers its module, and a module is what the next push sends: a module named `sudo`
-- built from a repository an agent made would grant whoever wrote it root on every node it is assigned.
-- So an outcome may register a module only from the repository the catalogue already builds it from — or,
-- for a module new to the catalogue, from a repository the catalogue already builds another module from.
-- Anything else — a module moved to another repository, a new module from a new repository — is the
-- operator's, at the controller's terminal. This column is how the take-in tells: true only for a build
-- request kept by a `build` or `replay --register` run at the terminal, never through a verb (whoever may
-- call a verb includes agents). False for every request kept before this column existed.
alter table build_request add column at_terminal boolean not null default false;
+20 -3
View File
@@ -38,6 +38,9 @@ type BuildRequest struct {
// unknown. Read as in flight until its outcome or its bound.
OutcomeUnknown string
At time.Time
// AtTerminal says the request was asked at the controller's terminal, never through a verb (novox/hq ADR
// 0266): what lets its outcome register a module from a repository the catalogue does not build it from.
AtTerminal bool
}
// Name is the module this request is expected to register, read from its directory: the last element of
@@ -73,16 +76,30 @@ func (i *Inventory) RecordBuildRequest(ctx context.Context, a BuildRequest) erro
notAsked = &a.NotAsked
}
if _, err := i.store.Pool().Exec(ctx,
`insert into build_request (id, repository, seat, source_path, ref, commit_hash, asked_for, not_asked, asked_at)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9)
`insert into build_request (id, repository, seat, source_path, ref, commit_hash, asked_for, not_asked, asked_at,
at_terminal)
values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
on conflict (id) do nothing`,
a.ID, a.Repository, a.Seat, strings.Trim(a.Path, "/"), a.Ref, a.Commit, a.For, notAsked, at); err != nil {
a.ID, a.Repository, a.Seat, strings.Trim(a.Path, "/"), a.Ref, a.Commit, a.For, notAsked, at,
a.AtTerminal); err != nil {
return err
}
_, err := i.store.Pool().Exec(ctx, `delete from build_request where asked_at < $1`, time.Now().Add(-KeptFor))
return err
}
// AskedAtTheTerminal says whether the build of this id was kept as asked at the controller's terminal (novox/hq
// ADR 0266). False for a build no request was kept for — a check, a dry run, an outcome nobody here asked for —
// and for every request asked through a verb.
func (i *Inventory) AskedAtTheTerminal(ctx context.Context, id string) (bool, error) {
var at bool
err := i.store.Pool().QueryRow(ctx, `select at_terminal from build_request where id = $1`, id).Scan(&at)
if errors.Is(err, pgx.ErrNoRows) {
return false, nil
}
return at, err
}
// MarkNotAsked says a kept build request was never handed over: the words are kept, unless its outcome was
// heard first.
func (i *Inventory) MarkNotAsked(ctx context.Context, id, why string) error {