108 lines
4.2 KiB
Go
108 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"time"
|
|
|
|
"git.cin.su/m/Assistant/adapters/postgres"
|
|
secretcontracts "git.cin.su/m/Assistant/contracts/secrets"
|
|
"git.cin.su/m/Assistant/contracts/work"
|
|
"git.cin.su/m/Assistant/modules/work/application"
|
|
"git.cin.su/m/Assistant/modules/work/ports"
|
|
platformsecrets "git.cin.su/m/Assistant/platform/secrets"
|
|
)
|
|
|
|
type memoryStore struct{ writes int }
|
|
|
|
func (s *memoryStore) SaveDispatchIntent(context.Context, work.AgentDispatchIntent) error {
|
|
s.writes++
|
|
return nil
|
|
}
|
|
func (s *memoryStore) SaveAgentLease(context.Context, work.AgentLease) error { s.writes++; return nil }
|
|
func (s *memoryStore) AcceptAgentCallback(context.Context, work.AgentCallback) error {
|
|
s.writes++
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
enabled := flag.Bool("enable-canary", false, "explicitly enable the manual canary")
|
|
implementation := flag.String("implementation", "fake-worker", "allowlisted deterministic implementation")
|
|
postgresMode := flag.Bool("postgres", false, "use the Work PostgreSQL repository instead of in-memory storage")
|
|
runID := flag.String("run-id", "", "optional unique canary run suffix; generated when omitted")
|
|
flag.Parse()
|
|
|
|
suffix := *runID
|
|
if suffix == "" {
|
|
suffix = fmt.Sprintf("%d", time.Now().UnixNano())
|
|
}
|
|
now := time.Now().UTC()
|
|
intent := work.AgentDispatchIntent{DispatchID: "manual-dispatch-" + suffix, IdempotencyKey: "manual-idempotency-" + suffix, DelegationID: work.DelegationID("manual-delegation-" + suffix), RunID: work.AgentRunID("manual-run-" + suffix), ImplementationID: *implementation, ImplementationRevision: 1, SourceRevision: "manual-source-" + suffix, WorktreeID: "manual-worktree-" + suffix, VerificationPlanRef: "manual-verification-" + suffix, CreatedAtUnixMillis: now.UnixMilli()}
|
|
var store ports.ExecutionStore = &memoryStore{}
|
|
var closeStore func()
|
|
if *postgresMode {
|
|
password, err := resolveDatabasePassword()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
repository, err := postgres.OpenWork(context.Background(), postgres.ContinuityConfig{Host: os.Getenv("POSTGRES_HOST"), Port: os.Getenv("POSTGRES_PORT"), Database: os.Getenv("POSTGRES_DATABASE"), User: os.Getenv("WORK_POSTGRES_USER"), Password: password})
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
store = repository
|
|
closeStore = repository.Close
|
|
}
|
|
if closeStore != nil {
|
|
defer closeStore()
|
|
}
|
|
result, err := application.ExecuteCanaryDryRun(context.Background(), store, application.CanaryConfig{Enabled: *enabled, ImplementationID: "fake-worker", MaxDispatches: 1}, 0, intent, "manual-worker", 1, now, 15*time.Minute)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
output := struct {
|
|
DispatchID string `json:"dispatch_id"`
|
|
RunID string `json:"run_id"`
|
|
CallbackCount int `json:"callback_count"`
|
|
StoreWrites int `json:"store_writes"`
|
|
}{result.Intent.DispatchID, string(result.Intent.RunID), result.CallbackCount(), 0}
|
|
if memory, ok := store.(*memoryStore); ok {
|
|
output.StoreWrites = memory.writes
|
|
}
|
|
if err := json.NewEncoder(os.Stdout).Encode(output); err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func resolveDatabasePassword() (string, error) {
|
|
if _, ok := os.LookupEnv("WORK_POSTGRES_PASSWORD"); ok {
|
|
return "", fmt.Errorf("WORK_POSTGRES_PASSWORD direct environment secret is forbidden")
|
|
}
|
|
path, ref := os.Getenv("WORK_POSTGRES_PASSWORD_FILE"), os.Getenv("WORK_POSTGRES_CREDENTIAL_REF")
|
|
if path == "" || ref == "" {
|
|
return "", fmt.Errorf("WORK_POSTGRES_PASSWORD_FILE and WORK_POSTGRES_CREDENTIAL_REF are required")
|
|
}
|
|
root := os.Getenv("SECRET_BACKEND_ROOT")
|
|
if root == "" {
|
|
root = "/run/secrets"
|
|
}
|
|
cleanRoot := filepath.Clean(root)
|
|
cleanPath := filepath.Clean(path)
|
|
if cleanPath != cleanRoot && !strings.HasPrefix(cleanPath, cleanRoot+string(os.PathSeparator)) {
|
|
return "", fmt.Errorf("database password file escapes protected secret root")
|
|
}
|
|
resolver, err := platformsecrets.NewFileResolver(cleanRoot)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return resolver.ResolveFile(secretcontracts.SecretFileRef{CredentialRef: secretcontracts.CredentialRef(ref), Purpose: secretcontracts.SecretPurposeDatabasePassword, Consumer: secretcontracts.RuntimeConsumerWorkWorker, Path: cleanPath})
|
|
}
|