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
+17 -1
View File
@@ -451,6 +451,10 @@ func buildOneAsked(ctx context.Context, source buildSource, path, ref string, wa
if err != nil {
return "", err
}
// Through a verb, only a repository the catalogue builds from (novox/hq ADR 0266).
if err := verbMayAsk(ctx, source, repository); err != nil {
return "", err
}
ident, err := openIdentity(ctx)
if err != nil {
@@ -500,8 +504,10 @@ func buildOneAsked(ctx context.Context, source buildSource, path, ref string, wa
// never before, so an ask that failed never reads as a build in flight. A dry run registers nothing, and
// is not kept.
keep := !dryRun && asker != ""
// Asked at the terminal is what lets its outcome register a module from a repository the catalogue does
// not build it from (novox/hq ADR 0266); never through a verb.
asked := inventory.BuildRequest{ID: request.ID, Repository: source.Repository, Seat: source.Seat, Path: path,
Ref: ref, For: asker}
Ref: ref, For: asker, AtTerminal: startedAtTheTerminal()}
if wait == 0 {
// Asked and not waited for (novox/hq issue 176): the outcome is the role's event, and the
@@ -631,6 +637,13 @@ func takeIn(ctx context.Context, inv *inventory.Inventory, result link.BuildResu
return manifest, kept, fmt.Errorf("%s built %s (%s), and the mesh does not register it: %w",
result.On, result.Repository, short(result.Commit), err)
}
// **Only from the repository the catalogue builds the module from** (novox/hq ADR 0266): else the trunk
// below is the trunk of whatever repository was built, which may be one an agent made — and a module named
// `sudo` from it would be what the next push sends. Another repository is the operator's, at the terminal.
if err := mayRegisterFrom(ctx, inv, manifest.Module, recorded, result.ID); err != nil {
return manifest, kept, fmt.Errorf("%s built %s (%s), recorded and not registered: %w", result.On,
manifest.Module, short(result.Commit), err)
}
// **Only a commit on the trunk is published** (novox/hq ADR 0238): a commit off its repository's
// default branch — a pull request's head, a feature branch built by hand, a `rebuild` or `replay
// --register` of one — is for checking, and is never a module's version; nothing could then send it.
@@ -719,6 +732,9 @@ func buildAndShow(ctx context.Context, source buildSource, path, ref string, wai
if err != nil {
return err
}
if err := verbMayAsk(ctx, source, repository); err != nil {
return err
}
ident, err := openIdentity(ctx)
if err != nil {
return err