activator: the claim path's mode comment says what the key's ensure does, the claim snapshot test pins the delivered configured key, and a failure message prints the own file's length (end sweep, task 4)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 files changed,
+16
−4
internal/activator/claim_instancekey_test.go+1 −1internal/activator/claim_snapshot.go+6 −2internal/activator/instancekey.go+3 −1internal/host/claim_instancekey_test.go+6 −0
diff --git a/internal/activator/claim_instancekey_test.go b/internal/activator/claim_instancekey_test.go| index 4d983f8c8..22011e68a 100644 |
| --- a/internal/activator/claim_instancekey_test.go |
| +++ b/internal/activator/claim_instancekey_test.go |
| @@ -104,7 +104,7 @@ func TestEnsureClaimAdminTokenMintsOnlyTheKeyWhenConfigSuppliesTheToken(t *testi |
| } |
| own := parseEnvBytes(raw) |
| if authorized != 1 || !wellFormedInstanceKey(own[InstanceKeyVar]) || own["CARLOS_ADMIN_TOKEN"] != "" { |
| - t.Fatalf("authorized %d, own file %q; want one guarded write with a key and no token", authorized, raw) |
| + t.Fatalf("authorized %d, own file %d bytes, key well formed %v, token present %v; want one guarded write with a key and no token", authorized, len(raw), wellFormedInstanceKey(own[InstanceKeyVar]), own["CARLOS_ADMIN_TOKEN"] != "") |
| } |
| vars, err := b.instanceEnv(rt) |
| if err != nil || vars["CARLOS_ADMIN_TOKEN"] != tok { |
diff --git a/internal/activator/claim_snapshot.go b/internal/activator/claim_snapshot.go| index 8aa7d43df..1e9b45835 100644 |
| --- a/internal/activator/claim_snapshot.go |
| +++ b/internal/activator/claim_snapshot.go |
| @@ -66,8 +66,12 @@ func (b *ExecBackend) EnsureClaimAdminToken(ctx context.Context, rt registry.Rou |
| // authorize is not called, but the file is still made durable before |
| // the launch source answers: a key whose mint failed its sync is never |
| // launched with until a sync succeeds (settleClaimInstanceEnv, ruling |
| - // 18). A file that needs its mode set takes the guarded path, which |
| - // sets it. |
| + // 18). A file that is not 0600 takes the guarded path. The key's |
| + // ensure sets the mode when the own file holds the key; when the key |
| + // is the configuration's, or the row is a replica, the ensure writes |
| + // nothing, the mode stays as it is, and the next launch of that row |
| + // asks the guard again. The token's mode has never been the claim |
| + // path's to tighten. |
| if vars["CARLOS_ADMIN_TOKEN"] != "" && (rt.Replica || vars[InstanceKeyVar] != "") { |
| err := b.settleClaimInstanceEnv(rt) |
| switch { |
diff --git a/internal/activator/instancekey.go b/internal/activator/instancekey.go| index 4a640502c..d760c64f9 100644 |
| --- a/internal/activator/instancekey.go |
| +++ b/internal/activator/instancekey.go |
| @@ -393,7 +393,9 @@ var errInstanceEnvNeedsWrite = errors.New("activator: the instance env file need |
| // file and its directory durable and writes nothing. fsync changes no |
| // byte, mode or name, so it is not a host write and runs without the |
| // claim's guard. A file that is not 0600 is errInstanceEnvNeedsWrite, and |
| -// the caller takes the guarded path, whose ensure sets the mode. |
| +// the caller takes the guarded path, whose ensure sets the mode when the |
| +// own file holds the key (and leaves it when the key is configured or the |
| +// row is a replica: EnsureClaimAdminToken). |
| func (b *ExecBackend) settleClaimInstanceEnv(rt registry.Route) error { |
| p := b.pathsFor(rt) |
| name := rt.Host + ".env" |
diff --git a/internal/host/claim_instancekey_test.go b/internal/host/claim_instancekey_test.go| index 733ab21ee..71c46b918 100644 |
| --- a/internal/host/claim_instancekey_test.go |
| +++ b/internal/host/claim_instancekey_test.go |
| @@ -4,6 +4,7 @@ import ( |
| "context" |
| "os" |
| "path/filepath" |
| + "slices" |
| "strings" |
| "testing" |
| "time" |
| @@ -139,4 +140,9 @@ func TestClaimSnapshotNamesTheDeliveredKeyAndItsSource(t *testing.T) { |
| if err != nil || snap.InstanceKeySource != instancekey.SourceConfig || snap.InstanceKeySHA256 != instancekey.Digest("from-config") { |
| t.Fatalf("configured key: source %q, %v", snap.InstanceKeySource, err) |
| } |
| + // The named key is the delivered key: Env carries the configured value, |
| + // not the own file's empty override (mergeEnv applies Effective). |
| + if !slices.Contains(snap.Env, activator.InstanceKeyVar+"=from-config") { |
| + t.Fatal("the snapshot names the configured key but its env does not deliver it") |
| + } |
| } |