Optional capabilities¶
Moderation, member lookup, interactive components and slash commands are
optional interfaces, discovered by type assertion rather than declared in
Actor.
if mod, ok := chatplatform.AsModerator(p); ok {
err := mod.TimeoutMember(ctx, userID, time.Hour, "repeated abuse")
}
Why not put them in Actor¶
Because a provider implementing none of them is legitimate.
A bridge that reads an IRC channel and posts replies is a useful provider. If
Actor required TimeoutMember, that provider would have to stub it and return
"unsupported" — telling the caller at runtime what the type system could have
told them at compile time. Multiply by four capabilities and every minimal
provider carries a dozen lying methods.
Type assertion inverts it. The provider implements what it can do; the caller asks. Neither pretends.
Declare what you implement¶
The conformance harness checks capability declarations in both directions, because both mistakes are silent:
- A claimed capability that is missing makes the harness look for something impossible.
- An implemented capability nobody declares is one nobody discovers. It works, and no consumer ever finds it.
Where the interactive surface stops¶
Interactive deliberately stops short of any platform's component model. No
rows, no custom-ID encoding, no message flags, and styling reduced to an
advisory hint that an unrecognised value renders as neutral rather than
failing.
Reproducing a component model would make this one vendor's API with different names. The contract carries what a support bot actually needs: offer some labelled choices, open a small form, answer, and replace the thing that was acted on.
UpdateSource earns its place for that last one. Without it, buttons stay live
after they have been used and a second moderator actions the same report.
Validation belongs in the spec types¶
PromptSpec, FormSpec and CommandSpec validate their own keys, and
providers call Validate before touching the wire.
Duplicate or empty keys are the failure worth catching early. A moderation card carries dismiss, delete and ban; routing an ambiguous key means taking the wrong action against a person. Better to refuse to post the card.