- Status: done
- Date: 2026-05-30
- Specs touched: docs/specs/BRAIN_HOST_PROTOCOL.md
Added GET /v1/identity/well-known → { malmo_app_uid, malmo_app_gid, malmo_shared_gid } to host-agent. This is the second host-side input the override generator (slice 4) needs, alongside ResolveHome (slice 2, host-agent-resolve-home.md). Where ResolveHome answers "what UID does this owner's personal instance run as," this endpoint answers the two host-identity facts that are not per-user: the shared service identity a household instance runs as (malmo-app), and the GID a shared-source folder mount joins (malmo-shared). Split out as its own slice because it is self-contained and independently testable — the enforcement work that consumes it lands next.
Code changes:
internal/protocol/host.go— newWellKnownIdentityResponse{MalmoAppUID, MalmoAppGID, MalmoSharedGID int}with JSON tagsmalmo_app_uid/malmo_app_gid/malmo_shared_gid.internal/hostagent/agent.go—WellKnownIdentity() (appUID, appGID, sharedGID int, err error)added to theUserManagerconsumer-side interface;wellKnownIdentityhandler registered inMountforGET /v1/identity/well-known; fake branch (UserMgr == nil) returns fixed dev constants2000/2000/2001; real branch delegates and maps any error to a generic 500 (no typed error — there is no unknown-user case here).internal/hostagent/usermgr/linux.go—WellKnownIdentityonLinuxUserManager:os/user.Lookup("malmo-app")for the service UID/GID,os/user.LookupGroup("malmo-shared")for the shared GID, each wrapped with context. These accounts are provisioned by the box build; absent on the dev box, where only the fake branch runs.internal/hostclient/hostclient.go—WellKnownIdentity(ctx)via the standarddohelper (GET /v1/identity/well-known). UnlikeResolveHomeit does not hand-roll the request, because there is no 404 to discriminate into a typed sentinel.- Tests:
internal/hostagent/agent_test.go(fake branch returns the fixed constants; delegate path; 500-on-error that asserts the response does not leak themalmo-applookup detail);internal/hostclient/hostclient_test.go(round-trip over the UNIX socket).stubUserMgrgains aWellKnownIdentitystub to satisfy the updated interface.
Realizes the new GET /v1/identity/well-known block under BRAIN_HOST_PROTOCOL.md # User info endpoints. Same Pattern A shape and fake/real branching as ResolveHome. The chosen fake constants (2000/2000/2001) sit below the per-user fake-UID range [3000, 3999] so service identities never collide with hashed user UIDs in the dev loop. The field semantics match APP_ISOLATION.md # User content: malmo_app_* is the household user:, malmo_shared_gid is the group_add for any shared-source mount.
- No consumer yet.
HostDriver(internal/lifecycle/docker.go) is deliberately not extended in this slice — the override generator that callsWellKnownIdentityis slice 4 proper.hostclient.Clientalready exposes the method; lifecycle picks it up next. cmd/host-agent-real/main.goneeds no change —LinuxUserManagergaining a method keeps satisfying the interface, so the endpoint is automatically live in the real binary.internal/hostagent/pamverifierstill fails to build here (CGOC.RTLD_NEXT); pre-existing, unrelated.
- Slice 4 — enforce in
writeOverride/writeEnv. Thread the user's per-folder elections (scope + source + subfolder) throughInstall; stampuser:(personal →ResolveHomeUID/GID, household →malmo-appfrom this slice), folder bind mounts from the elected source,group_addwithmalmo_shared_gidfor shared sources,devices, GPU, andMALMO_FOLDER_*. AddWellKnownIdentityto theHostDriverinterface. Server-side validate the elections ininternal/api(authoritative; install-plan is advisory) and audit rejections. Extendcatalog/whoamiwith afoldersdeclaration and verify a real dev-loop install perfeedback_verify_before_commit. - Slice 5 — consent + config UI.