Make the plan honest and the runbook's paths real
Two things that would have gone wrong on the first live run. The plan promised "create bot.avatar" and apply had no avatar code at all: /setuserpic needs a photo upload that is not implemented. A plan that promises an action apply silently skips is worse than one that admits the gap, because it makes every other line less trustworthy. The avatar is now deferred, with instructions for setting it by hand. The runbook wrote secrets to "<interface-path>/telegram/...", which is not what the code computes. An operator following it would have put api_id and api_hash somewhere the tool never looks, and found out at the first connection attempt. Both documents now carry the real paths -- <mount>/fluid-telegram/<campaign>/telegram/<key> -- with a copy-pasteable bao kv put for the one secret written by hand, and a verify step before the session is minted. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0172sgCZEEDJcnQmr4SGDvKa Assistant: claude-code Assistant-Model: opus Assistant-Process: 1361245@bnt-lap001 Assistant-Session: b3b428ef-f3e6-4688-b091-01f71461d66a
This commit is contained in:
parent
5ddfee8250
commit
014ee5c746
4 changed files with 90 additions and 18 deletions
|
|
@ -149,7 +149,14 @@ func planBot(p *Plan, sp *spec.Presence, rs *state.Resolved, live Live) error {
|
|||
sp.Bot.Name, len(sp.Bot.UsernamePreference), strings.Join(sp.Bot.UsernamePreference, ", ")))
|
||||
p.add(Create, "bot.profile", "set name, about text and description")
|
||||
if sp.Bot.Avatar != "" {
|
||||
p.add(Create, "bot.avatar", sp.Bot.Avatar)
|
||||
// apply does not set the avatar yet: /setuserpic needs a photo
|
||||
// upload, which is FT-WP-0002 T04's remaining piece. Say so, rather
|
||||
// than promising an action that would be silently skipped -- a plan
|
||||
// nobody can trust line by line is not worth reading.
|
||||
p.addWhy(Defer, "bot.avatar", sp.Bot.Avatar,
|
||||
"Not applied yet: setting a bot's picture needs a photo upload, which "+
|
||||
"is not implemented. Set it by hand in @BotFather with /setuserpic, "+
|
||||
"or leave it until the upload lands.")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,3 +211,23 @@ func TestVerifiedTestChannelReleasesPublic(t *testing.T) {
|
|||
t.Errorf("public should no longer be deferred:\n%s", p.Render())
|
||||
}
|
||||
}
|
||||
|
||||
// The plan must not promise an action apply will silently skip. The avatar is
|
||||
// the live case: /setuserpic needs an upload that is not implemented, so the
|
||||
// plan defers it with an explanation instead of claiming a create.
|
||||
func TestAvatarIsDeferredNotPromised(t *testing.T) {
|
||||
s := sp()
|
||||
s.Bot.Avatar = "presence/assets/avatar.png"
|
||||
p, _ := Compute(s, "sha256:x", &state.Resolved{}, fake{})
|
||||
|
||||
if find(p, Create, "bot.avatar") != nil {
|
||||
t.Fatal("plan promised an avatar create that apply does not perform")
|
||||
}
|
||||
a := find(p, Defer, "bot.avatar")
|
||||
if a == nil {
|
||||
t.Fatalf("expected the avatar to be deferred:\n%s", p.Render())
|
||||
}
|
||||
if !strings.Contains(a.Why, "setuserpic") {
|
||||
t.Errorf("deferral should say how to do it by hand: %q", a.Why)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue