Why: Direct HTTP and surface command dispatch could mutate RDM project facts without an analyzed committed-message manifest. Evidence: Command-bus, server, and app suites pass with a classification regression for formal writes and read/proof exceptions. Impact: Formal HTTP writes require a conversation anchor and committed proceed decision; surface writes fail closed until they can carry the same proof. Refs: TT-N03 TT-R01
30 lines
1.1 KiB
Go
30 lines
1.1 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"agent-system-backend/internal/cmdbus"
|
|
"agent-system-backend/internal/surfacesvc"
|
|
)
|
|
|
|
// dispatchSurfaceAction receives Owner from SurfaceService's authenticated
|
|
// caller. The button is acting for that user, so both Actor and Owner must be
|
|
// populated before the command bus writes its audit envelope.
|
|
func dispatchSurfaceAction(ctx context.Context, bus *cmdbus.Bus, d surfacesvc.ActionDispatch) (surfacesvc.ActionOutcome, error) {
|
|
if cmdbus.RequiresProjectWorkDecision(d.CommandID) {
|
|
return surfacesvc.ActionOutcome{}, fmt.Errorf("project formal action requires a committed conversation source preflight")
|
|
}
|
|
resp := bus.Dispatch(ctx, cmdbus.Request{ID: d.CommandID, Params: d.Params,
|
|
Entrance: "button", Actor: d.Owner, Owner: d.Owner, ConversationID: d.ConversationID})
|
|
state := "committed"
|
|
if resp.Receipt.State != "" {
|
|
state = string(resp.Receipt.State)
|
|
}
|
|
cardID := ""
|
|
if resp.Card != nil {
|
|
cardID = string(resp.Card.ID)
|
|
}
|
|
return surfacesvc.ActionOutcome{State: state, CardID: cardID, Receipt: resp.Receipt, Payload: resp.Payload}, nil
|
|
}
|