Files
attesto-go/cmd/attesto/main.go
Codex b06e59adb4 sdk(P1.10): embedded parity self-test + attesto doctor
A trimmed (~1.7 KB) copy of the cross-language parity vectors now ships inside
each package (Python package-data JSON, Go go:embed, TS generated module). On
the first hashing operation per process each SDK recomputes the commitment
hash, the receipt domain-hash, and an inclusion fold against the vendored
vectors and fails closed (AttestoSelfTestError / ErrSelfTest) on any mismatch
— a corrupted install or diverging runtime can never silently produce wrong
evidence. Result is cached (including failure); cost <5 ms once. Corrupting a
vendored vector is test-asserted to fail closed in all three languages. The
frozen canonical primitives are untouched; the gate lives in the commitment/
verify entry points built on top of them.

attesto doctor: Go CLI subcommand and Python attesto.doctor(), producing a
deterministic {"ok", "checks"} report — vendored self-test, head-store
writability, number-policy dry-run on a sample payload, Ed25519 availability
(Python), and with credentials: reachability, protocol-header acceptance, and
clock skew vs the server Date header (warn >30 s; webhooks break at 300 s).

package_artifact_policy allows exactly attesto/_selftest_vectors.json in the
wheel (verified: built wheel contains it, policy green). READMEs updated.
This completes the last Phase-1 build item.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 19:43:24 +02:00

1855 lines
53 KiB
Go

package main
import (
"archive/zip"
"bufio"
"bytes"
"context"
"crypto/sha256"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"time"
attesto "git.rotz.ai/rotzmediagroup/attesto-v1/sdk/go"
"git.rotz.ai/rotzmediagroup/attesto-v1/sdk/go/connectorkit"
)
const cliVersion = "0.2.0"
var supportedVerifyKindNames = []string{
"receipt",
"stream",
"window",
"checkpoint",
"consistency",
"anchor",
"ivc",
"bundle",
"truth-package",
}
type cliConfig struct {
BaseURL string `json:"baseUrl,omitempty"`
APIKey string `json:"apiKey,omitempty"`
Token string `json:"token,omitempty"`
}
type app struct {
out io.Writer
err io.Writer
env func(string) string
jsonOutput bool
baseURL string
apiKey string
token string
configPath string
}
func main() {
os.Exit(run(os.Args[1:], os.Stdout, os.Stderr, os.Getenv))
}
func run(args []string, stdout, stderr io.Writer, getenv func(string) string) int {
a := &app{out: stdout, err: stderr, env: getenv}
fs := flag.NewFlagSet("attesto", flag.ContinueOnError)
fs.SetOutput(stderr)
fs.BoolVar(&a.jsonOutput, "json", false, "write machine-readable JSON")
fs.StringVar(&a.baseURL, "base-url", "", "Attesto API base URL")
fs.StringVar(&a.apiKey, "api-key-env", "", "environment variable containing an Attesto system API key")
fs.StringVar(&a.token, "token-env", "", "environment variable containing a tenant bearer token")
fs.StringVar(&a.configPath, "config", "", "config file path")
if err := fs.Parse(args); err != nil {
return 2
}
remaining := fs.Args()
if len(remaining) == 0 {
a.fail("command required")
return 2
}
if a.apiKey != "" {
a.apiKey = getenv(a.apiKey)
}
if a.token != "" {
a.token = getenv(a.token)
}
if a.configPath == "" {
a.configPath = defaultConfigPath(getenv)
}
cfg, _ := readConfig(a.configPath)
if a.baseURL == "" {
a.baseURL = cfg.BaseURL
}
if a.apiKey == "" {
a.apiKey = cfg.APIKey
}
if a.token == "" {
a.token = cfg.Token
}
if a.baseURL == "" {
a.baseURL = attesto.DefaultBaseURL
}
if err := a.dispatch(context.Background(), remaining); err != nil {
a.fail(err.Error())
return 1
}
return 0
}
func (a *app) dispatch(ctx context.Context, args []string) error {
switch args[0] {
case "version":
return a.write(map[string]any{"name": "attesto", "version": cliVersion, "sdkVersion": attesto.SDKVersion, "verifyKinds": supportedVerifyKindNames})
case "config":
return a.config(args[1:])
case "login":
return a.configSet(args[1:])
case "logout":
return writeConfig(a.configPath, cliConfig{BaseURL: a.baseURL})
case "streams":
return a.streams(ctx, args[1:])
case "events":
return a.events(ctx, args[1:])
case "receipts":
return a.receipts(ctx, args[1:])
case "windows":
return a.verifyableObject(ctx, "windows", args[1:], attesto.VerifyWindow, "/v2/windows/")
case "checkpoints":
return a.checkpoints(ctx, args[1:])
case "witnesses":
return a.witnesses(ctx, args[1:])
case "anchors":
return a.anchors(ctx, args[1:])
case "bundles":
return a.bundles(ctx, args[1:])
case "verify":
return a.verify(ctx, args[1:])
case "fork-evidence":
return a.forkEvidence(ctx, args[1:])
case "quorum":
return a.quorum(ctx, args[1:])
case "ivc":
return a.ivc(ctx, args[1:])
case "connectors":
return a.connectors(ctx, args[1:])
case "local-vault":
return a.localVault(ctx, args[1:])
case "marketplace":
return a.marketplace(ctx, args[1:])
case "doctor":
return a.doctor(ctx, args[1:])
case "readiness":
return a.readiness(args[1:])
default:
return fmt.Errorf("unknown command: %s", args[0])
}
}
func (a *app) verify(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("verify subcommand required")
}
switch args[0] {
case "truth-package":
fs := flag.NewFlagSet("verify truth-package", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "truth package ZIP file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
if *file == "" {
return errors.New("--file is required")
}
return a.write(verifyTruthPackageZip(*file))
default:
_ = ctx
return fmt.Errorf("unknown verify subcommand: %s", args[0])
}
}
func (a *app) config(args []string) error {
if len(args) == 0 {
return errors.New("config subcommand required")
}
switch args[0] {
case "get":
cfg, err := readConfig(a.configPath)
if err != nil {
return err
}
return a.write(redactMap(map[string]any{"baseUrl": cfg.BaseURL, "apiKey": cfg.APIKey, "token": cfg.Token}))
case "set":
return a.configSet(args[1:])
default:
return fmt.Errorf("unknown config subcommand: %s", args[0])
}
}
func (a *app) configSet(args []string) error {
fs := flag.NewFlagSet("config set", flag.ContinueOnError)
fs.SetOutput(a.err)
baseURL := fs.String("base-url", a.baseURL, "API base URL")
apiKeyEnv := fs.String("api-key-env", "", "environment variable containing system API key")
tokenEnv := fs.String("token-env", "", "environment variable containing tenant bearer token")
if err := fs.Parse(args); err != nil {
return err
}
cfg, _ := readConfig(a.configPath)
cfg.BaseURL = *baseURL
if *apiKeyEnv != "" {
cfg.APIKey = a.env(*apiKeyEnv)
}
if *tokenEnv != "" {
cfg.Token = a.env(*tokenEnv)
}
if err := writeConfig(a.configPath, cfg); err != nil {
return err
}
return a.write(map[string]any{"ok": true, "path": a.configPath, "stored": redactMap(map[string]any{"baseUrl": cfg.BaseURL, "apiKey": cfg.APIKey, "token": cfg.Token})})
}
func (a *app) streams(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("streams subcommand required")
}
switch args[0] {
case "create":
fs := flag.NewFlagSet("streams create", flag.ContinueOnError)
fs.SetOutput(a.err)
useCase := fs.String("use-case", "", "stream use case")
policyID := fs.String("policy-id", "", "witness policy id")
metadataFile := fs.String("metadata-file", "", "JSON metadata file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
metadata, err := readOptionalObject(*metadataFile)
if err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
stream, err := client.CreateStream(ctx, attesto.StreamCreateInput{UseCase: *useCase, PolicyID: *policyID, Metadata: metadata})
if err != nil {
return err
}
return a.write(stream)
case "get":
fs := flag.NewFlagSet("streams get", flag.ContinueOnError)
fs.SetOutput(a.err)
streamID := fs.String("stream-id", "", "stream id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
stream, err := client.GetTenantStream(ctx, *streamID)
if err != nil {
return err
}
return a.write(stream)
case "head":
fs := flag.NewFlagSet("streams head", flag.ContinueOnError)
fs.SetOutput(a.err)
streamID := fs.String("stream-id", "", "stream id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
head, err := client.GetStreamHead(ctx, *streamID)
if err != nil {
return err
}
return a.write(head)
default:
return fmt.Errorf("unknown streams subcommand: %s", args[0])
}
}
func (a *app) events(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("events subcommand required")
}
client, err := a.systemClient()
if err != nil {
return err
}
switch args[0] {
case "log":
fs := flag.NewFlagSet("events log", flag.ContinueOnError)
fs.SetOutput(a.err)
streamID := fs.String("stream-id", "", "stream id")
sourceRef := fs.String("source-ref", "", "source reference")
eventType := fs.String("event-type", "inference", "event type")
occurredAt := fs.String("occurred-at", "", "source timestamp (RFC3339, defaults to current runtime time)")
payloadFile := fs.String("payload-file", "", "JSON payload file")
metadataFile := fs.String("metadata-file", "", "JSON metadata file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
payload, err := readOptionalObject(*payloadFile)
if err != nil {
return err
}
metadata, err := readOptionalObject(*metadataFile)
if err != nil {
return err
}
receipt, err := client.LogEvent(ctx, *streamID, attesto.EventInput{SourceRef: *sourceRef, EventType: *eventType, OccurredAt: *occurredAt, Payload: payload, Metadata: metadata})
if err != nil {
return err
}
return a.write(receipt)
case "batch":
fs := flag.NewFlagSet("events batch", flag.ContinueOnError)
fs.SetOutput(a.err)
streamID := fs.String("stream-id", "", "stream id")
file := fs.String("file", "", "JSON array or {events:[...]} file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
events, err := readEventsFile(*file)
if err != nil {
return err
}
result, err := client.LogEvents(ctx, *streamID, events)
if err != nil {
return err
}
return a.write(result)
default:
return fmt.Errorf("unknown events subcommand: %s", args[0])
}
}
func (a *app) receipts(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("receipts subcommand required")
}
switch args[0] {
case "get":
fs := flag.NewFlagSet("receipts get", flag.ContinueOnError)
fs.SetOutput(a.err)
eventID := fs.String("event-id", "", "stream event id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
receipt, err := client.GetReceipt(ctx, *eventID)
if err != nil {
return err
}
return a.write(receipt)
case "verify":
fs := flag.NewFlagSet("receipts verify", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "receipt JSON file")
publicKeyHex := fs.String("public-key-hex", "", "Ed25519 public key hex")
remote := fs.Bool("remote", false, "verify through /v2/verify/receipt")
if err := fs.Parse(args[1:]); err != nil {
return err
}
receipt, err := readReceipt(*file)
if err != nil {
return err
}
if *remote {
client, err := a.systemClient()
if err != nil {
return err
}
report, err := client.VerifyReceiptRemote(ctx, attesto.ReceiptVerifyInput{Receipt: receipt, PublicKeyHex: *publicKeyHex})
if err != nil {
return err
}
return a.write(report)
}
return a.write(attesto.VerifyReceiptOffline(receipt, *publicKeyHex))
default:
return fmt.Errorf("unknown receipts subcommand: %s", args[0])
}
}
func (a *app) verifyableObject(ctx context.Context, group string, args []string, kind attesto.VerifyKind, getPrefix string) error {
if len(args) == 0 {
return fmt.Errorf("%s subcommand required", group)
}
switch args[0] {
case "get":
fs := flag.NewFlagSet(group+" get", flag.ContinueOnError)
fs.SetOutput(a.err)
id := fs.String("id", "", "object id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
obj, err := getProofObject(ctx, client, kind, *id, getPrefix)
if err != nil {
return err
}
return a.write(obj)
case "verify":
return a.remoteVerify(ctx, args[1:], kind)
default:
return fmt.Errorf("unknown %s subcommand: %s", group, args[0])
}
}
// doctor diagnoses an SDK/CLI install: vendored parity self-test, head-store
// writability, number-policy dry-run on a sample payload, and (when an API key
// is configured) reachability, protocol-header acceptance, and clock skew vs
// the server Date header. Deterministic JSON report: {"ok": bool, "checks": {...}}.
func (a *app) doctor(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("doctor", flag.ContinueOnError)
fs.SetOutput(a.err)
samplePayload := fs.String("sample-payload", "", "JSON file with a sample payload for the number-policy dry-run")
if err := fs.Parse(args); err != nil {
return err
}
checks := map[string]map[string]any{}
pass := func(name string, extra map[string]any) {
if extra == nil {
extra = map[string]any{}
}
extra["ok"] = true
checks[name] = extra
}
fail := func(name string, err error) {
checks[name] = map[string]any{"ok": false, "error": err.Error()}
}
if err := attesto.EnsureSelfTest(); err != nil {
fail("self_test", err)
} else {
pass("self_test", nil)
}
headStore := attesto.NewFileHeadStore("")
headStore.Set("__doctor__", 1, strings.Repeat("0", 64))
if seq, hash, ok := headStore.Get("__doctor__"); ok && seq == 1 && hash == strings.Repeat("0", 64) {
pass("head_store", nil)
} else {
fail("head_store", errors.New("head store readback failed"))
}
if *samplePayload != "" {
raw, err := os.ReadFile(*samplePayload)
if err != nil {
return err
}
decoder := json.NewDecoder(bytes.NewReader(raw))
decoder.UseNumber()
var payload any
if err := decoder.Decode(&payload); err != nil {
return err
}
if err := attesto.AssertCommitmentSafeNumbers(payload, "$"); err != nil {
fail("number_policy", err)
} else {
pass("number_policy", nil)
}
}
if client, err := a.systemClient(); err == nil {
start := time.Now()
head, headErr := client.GetStreamHead(ctx, "__doctor-probe__")
_ = head
status := 0
var apiErr *attesto.APIError
if errors.As(headErr, &apiErr) {
status = apiErr.StatusCode
}
// Any HTTP-level answer (including 404 for the probe id) proves
// reachability + auth handling; transport errors do not.
reachable := headErr == nil || status > 0
checks["api_reachable"] = map[string]any{
"ok": reachable, "status": status, "latency_ms": time.Since(start).Milliseconds(),
}
checks["protocol_accepted"] = map[string]any{"ok": status != http.StatusUpgradeRequired, "status": status}
}
ok := true
for _, check := range checks {
if v, has := check["ok"].(bool); has && !v {
ok = false
}
}
return a.write(map[string]any{"ok": ok, "checks": checks})
}
func (a *app) anchors(ctx context.Context, args []string) error {
// `anchors verify <anchor_epoch_id> --rpc-url <url>` chains an API fetch
// with the on-chain check (eth_call getCommitment + tx receipt) against a
// customer-chosen RPC endpoint. Without --rpc-url, all subcommands keep the
// existing get / remote-verify behavior.
if len(args) > 0 && args[0] == "verify" {
rest := args[1:]
positional := ""
if len(rest) > 0 && !strings.HasPrefix(rest[0], "-") {
positional, rest = rest[0], rest[1:]
}
fs := flag.NewFlagSet("anchors verify", flag.ContinueOnError)
fs.SetOutput(a.err)
id := fs.String("id", positional, "anchor epoch id")
rpcURL := fs.String("rpc-url", "", "JSON-RPC endpoint for the anchor's chain")
timeoutS := fs.Int("timeout-s", 15, "RPC timeout in seconds")
file := fs.String("file", "", "proof object JSON file (remote verify mode)")
publicKeyHex := fs.String("public-key-hex", "", "Ed25519 public key hex (remote verify mode)")
if err := fs.Parse(rest); err != nil {
return err
}
if *rpcURL == "" {
fallback := []string{}
if *file != "" {
fallback = append(fallback, "--file", *file)
}
if *publicKeyHex != "" {
fallback = append(fallback, "--public-key-hex", *publicKeyHex)
}
return a.remoteVerify(ctx, fallback, attesto.VerifyAnchor)
}
if *id == "" {
return errors.New("anchor epoch id is required (positional or --id)")
}
client, err := a.systemClient()
if err != nil {
return err
}
anchor, err := client.GetAnchorEpoch(ctx, *id)
if err != nil {
return err
}
report := attesto.VerifyAnchorOnchain(ctx, anchor, *rpcURL, time.Duration(*timeoutS)*time.Second)
return a.write(report)
}
return a.verifyableObject(ctx, "anchors", args, attesto.VerifyAnchor, "/v2/anchors/")
}
func (a *app) checkpoints(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("checkpoints subcommand required")
}
if args[0] == "consistency" {
fs := flag.NewFlagSet("checkpoints consistency", flag.ContinueOnError)
fs.SetOutput(a.err)
checkpointID := fs.String("checkpoint-id", "", "target checkpoint id")
fromID := fs.String("from", "", "source checkpoint id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
obj, err := client.GetCheckpointConsistency(ctx, *checkpointID, *fromID)
if err != nil {
return err
}
return a.write(obj)
}
return a.verifyableObject(ctx, "checkpoints", args, attesto.VerifyCheckpoint, "/v2/checkpoints/")
}
func (a *app) witnesses(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("witnesses subcommand required")
}
switch args[0] {
case "policies":
fs := flag.NewFlagSet("witnesses policies", flag.ContinueOnError)
fs.SetOutput(a.err)
policyID := fs.String("policy-id", "", "policy id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
policy, err := client.GetWitnessPolicy(ctx, *policyID)
if err != nil {
return err
}
return a.write(policy)
case "status", "receipts":
fs := flag.NewFlagSet("witnesses "+args[0], flag.ContinueOnError)
fs.SetOutput(a.err)
streamID := fs.String("stream-id", "", "stream id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
state, err := client.GetTenantProofState(ctx, *streamID)
if err != nil {
return err
}
return a.write(state)
default:
return fmt.Errorf("unknown witnesses subcommand: %s", args[0])
}
}
func (a *app) bundles(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("bundles subcommand required")
}
switch args[0] {
case "build":
fs := flag.NewFlagSet("bundles build", flag.ContinueOnError)
fs.SetOutput(a.err)
fromID := fs.String("from", "", "from checkpoint id")
toID := fs.String("to", "", "to checkpoint id")
tenant := fs.Bool("tenant", false, "use tenant audit-pack endpoint")
if err := fs.Parse(args[1:]); err != nil {
return err
}
if *tenant {
client, err := a.bearerClient()
if err != nil {
return err
}
bundle, err := client.BuildTenantAuditPack(ctx, *fromID, *toID)
if err != nil {
return err
}
return a.write(bundle)
}
client, err := a.systemClient()
if err != nil {
return err
}
bundle, err := client.BuildVerifierBundle(ctx, *fromID, *toID)
if err != nil {
return err
}
return a.write(bundle)
case "get":
fs := flag.NewFlagSet("bundles get", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "local verifier bundle JSON file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
return a.write(obj)
case "verify":
return a.remoteVerify(ctx, args[1:], attesto.VerifyBundle)
case "offline-verify":
fs := flag.NewFlagSet("bundles offline-verify", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "bundle JSON file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
return a.write(verifyBundleHash(obj))
default:
return fmt.Errorf("unknown bundles subcommand: %s", args[0])
}
}
func (a *app) forkEvidence(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("fork-evidence subcommand required")
}
switch args[0] {
case "inspect":
fs := flag.NewFlagSet("fork-evidence inspect", flag.ContinueOnError)
fs.SetOutput(a.err)
streamID := fs.String("stream-id", "", "stream id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
forks, err := client.ListForkEvidence(ctx, *streamID, 100, 0)
if err != nil {
return err
}
return a.write(forks)
case "verify":
fs := flag.NewFlagSet("fork-evidence verify", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "fork evidence JSON file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
return a.write(verifyDomainObject("fork", obj, "evidence", "evidenceHash", "evidence_hash"))
default:
return fmt.Errorf("unknown fork-evidence subcommand: %s", args[0])
}
}
func (a *app) quorum(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("quorum subcommand required")
}
switch args[0] {
case "inspect":
fs := flag.NewFlagSet("quorum inspect", flag.ContinueOnError)
fs.SetOutput(a.err)
streamID := fs.String("stream-id", "", "stream id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
state, err := client.GetTenantProofState(ctx, *streamID)
if err != nil {
return err
}
return a.write(state)
case "verify":
fs := flag.NewFlagSet("quorum verify", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "quorum JSON file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
return a.write(verifyQuorumObject(obj))
default:
return fmt.Errorf("unknown quorum subcommand: %s", args[0])
}
}
func (a *app) ivc(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("ivc subcommand required")
}
if args[0] != "epochs" {
return fmt.Errorf("unknown ivc subcommand: %s", args[0])
}
if len(args) < 2 {
return errors.New("ivc epochs subcommand required")
}
switch args[1] {
case "get":
fs := flag.NewFlagSet("ivc epochs get", flag.ContinueOnError)
fs.SetOutput(a.err)
id := fs.String("id", "", "ivc epoch id")
if err := fs.Parse(args[2:]); err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
obj, err := client.GetIVCEpoch(ctx, *id)
if err != nil {
return err
}
return a.write(obj)
case "verify":
return a.remoteVerify(ctx, args[2:], attesto.VerifyIVC)
default:
return fmt.Errorf("unknown ivc epochs subcommand: %s", args[1])
}
}
func (a *app) connectors(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("connectors subcommand required")
}
switch args[0] {
case "create":
return a.connectorCreate(ctx, args[1:])
case "ingest":
return a.connectorIngest(ctx, args[1:])
case "revoke":
return a.connectorRevoke(ctx, args[1:])
case "verify":
fs := flag.NewFlagSet("connectors verify", flag.ContinueOnError)
fs.SetOutput(a.err)
secretEnv := fs.String("secret-env", "", "environment variable containing connector secret")
file := fs.String("file", "", "event JSON file")
timestamp := fs.Int64("timestamp", 0, "timestamp used for expected signature")
signature := fs.String("signature", "", "signature hex to verify")
if err := fs.Parse(args[1:]); err != nil {
return err
}
raw, err := os.ReadFile(*file)
if err != nil {
return err
}
_, expected := attesto.SignConnectorWebhookPayload(a.env(*secretEnv), raw, *timestamp)
return a.write(map[string]any{"ok": hmacEqual(expected, *signature), "expectedSignatureMatches": hmacEqual(expected, *signature)})
default:
return fmt.Errorf("unknown connectors subcommand: %s", args[0])
}
}
func (a *app) connectorCreate(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("connectors create", flag.ContinueOnError)
fs.SetOutput(a.err)
kind := fs.String("type", "", "signed-webhook, s3-object, or repository-webhook")
file := fs.String("file", "", "connector create JSON file")
if err := fs.Parse(args); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
raw, err := os.ReadFile(*file)
if err != nil {
return err
}
switch *kind {
case "signed-webhook":
var input attesto.ConnectorCreateInput
if err := json.Unmarshal(raw, &input); err != nil {
return err
}
out, err := client.CreateSignedWebhookConnector(ctx, input)
if err != nil {
return err
}
return a.write(out)
case "s3-object":
var input attesto.S3ConnectorCreateInput
if err := json.Unmarshal(raw, &input); err != nil {
return err
}
out, err := client.CreateS3ObjectConnector(ctx, input)
if err != nil {
return err
}
return a.write(out)
case "repository-webhook":
var input attesto.RepositoryConnectorCreateInput
if err := json.Unmarshal(raw, &input); err != nil {
return err
}
out, err := client.CreateRepositoryWebhookConnector(ctx, input)
if err != nil {
return err
}
return a.write(out)
default:
return errors.New("connector type must be signed-webhook, s3-object, or repository-webhook")
}
}
func (a *app) connectorIngest(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("connectors ingest", flag.ContinueOnError)
fs.SetOutput(a.err)
kind := fs.String("type", "signed-webhook", "signed-webhook or repository-webhook")
connectorID := fs.String("connector-id", "", "connector id")
file := fs.String("file", "", "event JSON file")
secretEnv := fs.String("secret-env", "", "environment variable containing signed-webhook secret")
headersFile := fs.String("headers-file", "", "repository webhook headers JSON file")
if err := fs.Parse(args); err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
raw, err := os.ReadFile(*file)
if err != nil {
return err
}
if *kind == "repository-webhook" {
headers, err := readStringMap(*headersFile)
if err != nil {
return err
}
out, err := client.IngestRepositoryWebhookEvent(ctx, *connectorID, raw, headers)
if err != nil {
return err
}
return a.write(out)
}
var event attesto.EventInput
if err := json.Unmarshal(raw, &event); err != nil {
return err
}
out, err := client.IngestSignedWebhookEvent(ctx, *connectorID, event, a.env(*secretEnv))
if err != nil {
return err
}
return a.write(out)
}
func (a *app) connectorRevoke(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("connectors revoke", flag.ContinueOnError)
fs.SetOutput(a.err)
kind := fs.String("type", "", "signed-webhook, s3-object, or repository-webhook")
connectorID := fs.String("connector-id", "", "connector id")
if err := fs.Parse(args); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
switch *kind {
case "signed-webhook":
return client.RevokeSignedWebhookConnector(ctx, *connectorID)
case "s3-object":
return client.RevokeS3ObjectConnector(ctx, *connectorID)
case "repository-webhook":
return client.RevokeRepositoryWebhookConnector(ctx, *connectorID)
default:
return errors.New("connector type must be signed-webhook, s3-object, or repository-webhook")
}
}
func (a *app) localVault(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("local-vault subcommand required")
}
switch args[0] {
case "install":
fs := flag.NewFlagSet("local-vault install", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "installation JSON file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
raw, err := os.ReadFile(*file)
if err != nil {
return err
}
var input attesto.LocalVaultInstallationCreateInput
if err := json.Unmarshal(raw, &input); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
out, err := client.CreateLocalVaultInstallation(ctx, input)
if err != nil {
return err
}
return a.write(out)
case "relay":
fs := flag.NewFlagSet("local-vault relay", flag.ContinueOnError)
fs.SetOutput(a.err)
installationID := fs.String("installation-id", "", "installation id")
file := fs.String("file", "", "relay JSON file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
out, err := client.RelayLocalVaultEvent(ctx, *installationID, objectField(obj, "envelope"), objectField(obj, "payload"), stringField(obj, "envelopeHash", "envelope_hash"), stringField(obj, "signatureHex", "signature_hex"), stringField(obj, "publicKeyHex", "public_key_hex"))
if err != nil {
return err
}
return a.write(out)
case "spool":
return a.localVaultSpool(args[1:])
case "status":
return a.localVaultStatus(args[1:])
case "witness":
return a.localVaultWitness(ctx, args[1:], false)
case "fork-evidence":
return a.localVaultWitness(ctx, args[1:], true)
case "revoke":
fs := flag.NewFlagSet("local-vault revoke", flag.ContinueOnError)
fs.SetOutput(a.err)
installationID := fs.String("installation-id", "", "installation id")
if err := fs.Parse(args[1:]); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
return client.RevokeLocalVaultInstallation(ctx, *installationID)
default:
return fmt.Errorf("unknown local-vault subcommand: %s", args[0])
}
}
func (a *app) localVaultSpool(args []string) error {
fs := flag.NewFlagSet("local-vault spool", flag.ContinueOnError)
fs.SetOutput(a.err)
spoolFile := fs.String("spool-file", "", "spool JSONL path")
file := fs.String("file", "", "event JSON file to append")
if err := fs.Parse(args); err != nil {
return err
}
raw, err := os.ReadFile(*file)
if err != nil {
return err
}
var obj any
if err := json.Unmarshal(raw, &obj); err != nil {
return err
}
if err := os.MkdirAll(filepath.Dir(*spoolFile), 0o700); err != nil {
return err
}
fh, err := os.OpenFile(*spoolFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600)
if err != nil {
return err
}
defer fh.Close()
canonical, err := attesto.CanonicalJSON(obj)
if err != nil {
return err
}
if _, err := fh.Write(append(canonical, '\n')); err != nil {
return err
}
return a.write(map[string]any{"ok": true, "spoolFile": *spoolFile})
}
func (a *app) localVaultStatus(args []string) error {
fs := flag.NewFlagSet("local-vault status", flag.ContinueOnError)
fs.SetOutput(a.err)
spoolFile := fs.String("spool-file", "", "spool JSONL path")
if err := fs.Parse(args); err != nil {
return err
}
fh, err := os.Open(*spoolFile)
if err != nil {
return err
}
defer fh.Close()
var count int
scanner := bufio.NewScanner(fh)
for scanner.Scan() {
count++
}
if err := scanner.Err(); err != nil {
return err
}
info, err := os.Stat(*spoolFile)
if err != nil {
return err
}
return a.write(map[string]any{"ok": true, "spoolFile": *spoolFile, "events": count, "bytes": info.Size()})
}
func (a *app) localVaultWitness(ctx context.Context, args []string, fork bool) error {
fs := flag.NewFlagSet("local-vault witness", flag.ContinueOnError)
fs.SetOutput(a.err)
installationID := fs.String("installation-id", "", "installation id")
file := fs.String("file", "", "witness receipt or fork evidence JSON file")
if err := fs.Parse(args); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
if fork {
out, err := client.SubmitLocalVaultForkEvidence(ctx, *installationID, obj)
if err != nil {
return err
}
return a.write(out)
}
out, err := client.SubmitLocalVaultWitnessReceipt(ctx, *installationID, obj)
if err != nil {
return err
}
return a.write(out)
}
func (a *app) marketplace(ctx context.Context, args []string) error {
if len(args) == 0 {
return errors.New("marketplace subcommand required")
}
switch args[0] {
case "init":
return a.marketplaceInit(args[1:])
case "validate":
return a.marketplaceValidate(args[1:])
case "submit":
return a.marketplaceSubmit(ctx, args[1:])
case "review-list":
return a.marketplaceReviewList(ctx, args[1:])
case "publish":
return a.marketplacePublish(ctx, args[1:])
default:
return fmt.Errorf("unknown marketplace subcommand: %s", args[0])
}
}
func (a *app) marketplaceInit(args []string) error {
fs := flag.NewFlagSet("marketplace init", flag.ContinueOnError)
fs.SetOutput(a.err)
output := fs.String("output", "", "manifest output path")
slug := fs.String("slug", "", "lower-kebab-case connector slug")
name := fs.String("name", "", "connector display name")
version := fs.String("version", "", "semantic version")
category := fs.String("category", "", "marketplace category")
summary := fs.String("summary", "", "short public summary")
description := fs.String("description", "", "public description")
publisherSlug := fs.String("publisher-slug", "", "publisher slug")
publisherName := fs.String("publisher-name", "", "publisher display name")
repositoryURL := fs.String("repository-url", "", "public release source URL")
docsURL := fs.String("docs-url", "", "public documentation URL")
capabilitiesRaw := fs.String("capabilities", "", "comma-separated capabilities")
providerURL := fs.String("provider-url", "", "provider website URL")
authMode := fs.String("auth-mode", "", "connector auth mode")
authScopesRaw := fs.String("auth-scopes", "", "comma-separated provider scopes")
syncModesRaw := fs.String("sync-modes", "", "comma-separated sync modes")
eventTypesRaw := fs.String("event-types", "", "comma-separated source event types")
canaryRef := fs.String("canary-ref", "", "real canary/test-account evidence reference")
if err := fs.Parse(args); err != nil {
return err
}
if *output == "" {
return errors.New("output is required")
}
authScopes := splitCSV(*authScopesRaw)
syncModes := splitCSV(*syncModesRaw)
eventTypes := splitCSV(*eventTypesRaw)
manifest := connectorkit.Manifest{
SchemaVersion: "attesto.connector.v2",
Slug: *slug,
Name: *name,
Version: *version,
AssetType: "connector",
Category: *category,
Summary: *summary,
Description: *description,
Publisher: map[string]string{
"slug": *publisherSlug,
"name": *publisherName,
},
Repository: map[string]string{"url": *repositoryURL},
Documentation: map[string]string{
"url": *docsURL,
},
Capabilities: splitCSV(*capabilitiesRaw),
Evidence: map[string]bool{
"offlineVerification": true,
"receipts": true,
"witnessCompatible": true,
},
Security: map[string]bool{
"dependencyScan": true,
"secretScan": true,
},
SupportedLanguages: []string{"en", "nl", "de", "fr", "es", "pl", "it"},
Provider: map[string]any{
"id": *slug,
"name": *name,
"websiteUrl": *providerURL,
},
Auth: map[string]any{
"mode": *authMode,
"scopes": authScopes,
},
Sync: map[string]any{
"modes": syncModes,
"supportsReplay": true,
"rateLimitPolicy": "provider-documented",
},
EventTypes: eventTypes,
SourceTime: map[string]any{
"required": true,
"timezonePolicy": "source-timestamp-with-offset-required",
},
ConfigSchema: map[string]any{"type": "object"},
SecretSchema: map[string]any{"type": "object"},
Diagnostics: map[string]any{
"providerAuthStatus": true,
"replayConflictCheck": true,
"revocationCheck": true,
"syncLag": true,
"testConnection": true,
},
Runtime: map[string]any{
"officialConnectorKit": true,
"sdkSurfaces": []string{"python", "typescript", "go", "cli"},
"requiredMethods": []string{
"metadata",
"validateConfig",
"testConnection",
"sync",
"handleWebhook",
"emitProofstreamEvent",
"diagnostics",
"revoke",
},
"canary": map[string]any{
"status": "green",
"ref": *canaryRef,
},
},
InstallRequirements: map[string]any{
"tenantLoginRequired": true,
"entitlementRequired": true,
},
Changelog: []map[string]any{
{
"version": *version,
"changes": []string{"Initial production connector manifest."},
},
},
}
if len(manifest.Capabilities) == 0 {
return errors.New("at least one capability is required")
}
result := connectorkit.ValidateManifest(manifest)
if !result.OK {
return a.write(map[string]any{"ok": false, "findings": result.Findings})
}
raw, err := json.MarshalIndent(manifest, "", " ")
if err != nil {
return err
}
if err := os.WriteFile(*output, append(raw, '\n'), 0o600); err != nil {
return err
}
return a.write(map[string]any{"ok": true, "manifest": *output, "evidenceScore": result.EvidenceScore, "tier": result.Tier})
}
func (a *app) marketplaceValidate(args []string) error {
fs := flag.NewFlagSet("marketplace validate", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("manifest-file", "", "connector manifest JSON file")
if err := fs.Parse(args); err != nil {
return err
}
manifest, err := readConnectorManifest(*file)
if err != nil {
return err
}
result := connectorkit.ValidateManifest(manifest)
return a.write(map[string]any{"ok": result.OK, "evidenceScore": result.EvidenceScore, "tier": result.Tier, "findings": result.Findings})
}
func (a *app) marketplaceSubmit(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("marketplace submit", flag.ContinueOnError)
fs.SetOutput(a.err)
manifestFile := fs.String("manifest-file", "", "connector manifest JSON file")
sourceRef := fs.String("source-ref", "", "real connector release source URL")
visibility := fs.String("visibility", "private", "private or public")
pricingModel := fs.String("pricing-model", "free", "free or paid")
priceCents := fs.Int("price-cents", 0, "price in cents for paid assets")
if err := fs.Parse(args); err != nil {
return err
}
manifest, err := readConnectorManifest(*manifestFile)
if err != nil {
return err
}
result := connectorkit.ValidateManifest(manifest)
if !result.OK {
return fmt.Errorf("manifest validation failed: %d finding(s)", len(result.Findings))
}
rawManifest, err := manifestToMap(manifest)
if err != nil {
return err
}
var price *int
if *pricingModel == "paid" {
price = priceCents
}
client, err := a.bearerClient()
if err != nil {
return err
}
out, err := client.SubmitMarketplaceAsset(ctx, attesto.MarketplaceAssetSubmitInput{
Manifest: rawManifest,
SourceRef: *sourceRef,
Visibility: *visibility,
PricingModel: *pricingModel,
PriceCents: price,
})
if err != nil {
return err
}
return a.write(out)
}
func (a *app) marketplaceReviewList(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("marketplace review-list", flag.ContinueOnError)
fs.SetOutput(a.err)
state := fs.String("state", "pending", "pending, published, rejected, revoked, or all")
if err := fs.Parse(args); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
out, err := client.ListMarketplaceReviewAssets(ctx, *state)
if err != nil {
return err
}
return a.write(out)
}
func (a *app) marketplacePublish(ctx context.Context, args []string) error {
fs := flag.NewFlagSet("marketplace publish", flag.ContinueOnError)
fs.SetOutput(a.err)
slug := fs.String("slug", "", "marketplace asset slug")
reason := fs.String("reason", "", "review reason")
if err := fs.Parse(args); err != nil {
return err
}
client, err := a.bearerClient()
if err != nil {
return err
}
out, err := client.ApproveMarketplaceAsset(ctx, *slug, *reason)
if err != nil {
return err
}
return a.write(out)
}
func (a *app) readiness(args []string) error {
if len(args) == 0 {
return errors.New("readiness subcommand required")
}
defaults := map[string]string{
"lifecycle": "release/attesto-2.0-lifecycle-readiness/result.json",
"fork-defense": "release/attesto-2.0-fork-defense-readiness/result.json",
"quorum": "release/attesto-2.0-quorum-readiness/result.json",
"assurance": "release/attesto-2.0-assurance-readiness/result.json",
"connectors": "release/attesto-2.0-connector-assurance-readiness/result.json",
"local-vault": "release/attesto-2.0-local-vault-assurance-readiness/result.json",
"nova": "release/attesto-2.0-nova-evolution-readiness/result.json",
"production": "release/attesto-2.0-production-readiness/manifest.json",
}
path, ok := defaults[args[0]]
if !ok {
return fmt.Errorf("unknown readiness subcommand: %s", args[0])
}
fs := flag.NewFlagSet("readiness "+args[0], flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", path, "readiness JSON file")
if err := fs.Parse(args[1:]); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
return a.write(validateReadiness(args[0], *file, obj))
}
func (a *app) remoteVerify(ctx context.Context, args []string, kind attesto.VerifyKind) error {
fs := flag.NewFlagSet("verify", flag.ContinueOnError)
fs.SetOutput(a.err)
file := fs.String("file", "", "proof object JSON file")
publicKeyHex := fs.String("public-key-hex", "", "Ed25519 public key hex when required")
if err := fs.Parse(args); err != nil {
return err
}
obj, err := readObject(*file)
if err != nil {
return err
}
client, err := a.systemClient()
if err != nil {
return err
}
report, err := client.VerifyObjectRemote(ctx, attesto.OfflineVerifyInput{Kind: kind, Object: obj, PublicKeyHex: *publicKeyHex})
if err != nil {
return err
}
return a.write(report)
}
func (a *app) systemClient() (*attesto.Client, error) {
if a.apiKey == "" {
return nil, errors.New("system API key required; configure it with --api-key-env or attesto config set --api-key-env")
}
return attesto.NewClient(a.apiKey, attesto.WithBaseURL(a.baseURL), attesto.WithHTTPClient(http.DefaultClient))
}
func (a *app) bearerClient() (*attesto.Client, error) {
if a.token == "" {
return nil, errors.New("tenant bearer token required; configure it with --token-env or attesto config set --token-env")
}
return attesto.NewBearerClient(a.token, attesto.WithBaseURL(a.baseURL), attesto.WithHTTPClient(http.DefaultClient))
}
func (a *app) write(value any) error {
value = redactValue(value)
encoder := json.NewEncoder(a.out)
encoder.SetEscapeHTML(false)
if a.jsonOutput {
encoder.SetIndent("", " ")
}
return encoder.Encode(value)
}
func (a *app) fail(message string) {
_ = json.NewEncoder(a.err).Encode(map[string]any{"ok": false, "error": sanitize(message)})
}
func readObject(path string) (attesto.M, error) {
if path == "" {
return nil, errors.New("file is required")
}
raw, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var obj attesto.M
if err := json.Unmarshal(raw, &obj); err != nil {
return nil, err
}
return obj, nil
}
func readOptionalObject(path string) (attesto.M, error) {
if path == "" {
return attesto.M{}, nil
}
return readObject(path)
}
func readReceipt(path string) (attesto.SignedReceipt, error) {
obj, err := readObject(path)
if err != nil {
return attesto.SignedReceipt{}, err
}
if nested, ok := obj["receipt"].(map[string]any); ok {
obj = nested
}
raw, err := json.Marshal(obj)
if err != nil {
return attesto.SignedReceipt{}, err
}
var receipt attesto.SignedReceipt
return receipt, json.Unmarshal(raw, &receipt)
}
func readEventsFile(path string) ([]attesto.EventInput, error) {
raw, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var wrapper struct {
Events []attesto.EventInput `json:"events"`
}
if err := json.Unmarshal(raw, &wrapper); err == nil && wrapper.Events != nil {
return wrapper.Events, nil
}
var events []attesto.EventInput
return events, json.Unmarshal(raw, &events)
}
func readStringMap(path string) (map[string]string, error) {
raw, err := os.ReadFile(path)
if err != nil {
return nil, err
}
var out map[string]string
return out, json.Unmarshal(raw, &out)
}
func readConnectorManifest(path string) (connectorkit.Manifest, error) {
raw, err := os.ReadFile(path)
if err != nil {
return connectorkit.Manifest{}, err
}
var manifest connectorkit.Manifest
return manifest, json.Unmarshal(raw, &manifest)
}
func manifestToMap(manifest connectorkit.Manifest) (attesto.M, error) {
raw, err := json.Marshal(manifest)
if err != nil {
return nil, err
}
var out attesto.M
return out, json.Unmarshal(raw, &out)
}
func splitCSV(raw string) []string {
values := []string{}
for _, part := range strings.Split(raw, ",") {
value := strings.TrimSpace(part)
if value != "" {
values = append(values, value)
}
}
return values
}
func getProofObject(ctx context.Context, client *attesto.Client, kind attesto.VerifyKind, id string, _ string) (attesto.M, error) {
switch kind {
case attesto.VerifyWindow:
return client.GetWindow(ctx, id)
case attesto.VerifyCheckpoint:
return client.GetCheckpoint(ctx, id)
case attesto.VerifyAnchor:
return client.GetAnchorEpoch(ctx, id)
case attesto.VerifyIVC:
return client.GetIVCEpoch(ctx, id)
default:
return nil, fmt.Errorf("get is not defined for proof object kind %s", kind)
}
}
func verifyBundleHash(obj attesto.M) map[string]any {
return verifyDomainObject("bundle", obj, "payload", "bundleHash", "bundle_hash")
}
func verifyTruthPackageZip(path string) map[string]any {
problems := []string{}
raw, err := os.ReadFile(path)
if err != nil {
return map[string]any{"ok": false, "problems": []string{err.Error()}}
}
packageHash := fmt.Sprintf("%x", sha256.Sum256(raw))
reader, err := zip.OpenReader(path)
if err != nil {
return map[string]any{"ok": false, "packageSha256": packageHash, "problems": []string{err.Error()}}
}
defer reader.Close()
entries := map[string]*zip.File{}
for _, item := range reader.File {
name := item.Name
if truthPackageForbiddenZipPath(name) {
problems = append(problems, "forbidden ZIP entry: "+name)
continue
}
entries[name] = item
}
manifestFile := entries["attesto.truth-package.manifest.json"]
if manifestFile == nil {
problems = append(problems, "attesto.truth-package.manifest.json missing")
return map[string]any{"ok": false, "packageSha256": packageHash, "problems": problems}
}
manifestBytes, err := readZipFile(manifestFile)
if err != nil {
problems = append(problems, "truth package manifest read failed: "+err.Error())
return map[string]any{"ok": false, "packageSha256": packageHash, "problems": problems}
}
manifestHash := fmt.Sprintf("%x", sha256.Sum256(manifestBytes))
var manifest map[string]any
if err := json.Unmarshal(manifestBytes, &manifest); err != nil {
problems = append(problems, "truth package manifest is not JSON: "+err.Error())
return map[string]any{"ok": false, "packageSha256": packageHash, "manifestSha256": manifestHash, "problems": problems}
}
if stringField(manifest, "schema") != "attesto.truth-package.manifest.v1" {
problems = append(problems, "truth package manifest schema mismatch")
}
verifiedArtifacts := 0
allowedEntries := map[string]bool{
"attesto.truth-package.manifest.json": true,
"attesto.sig.json": true,
}
if artifacts, ok := manifest["artifacts"].([]any); ok {
for _, artifact := range artifacts {
row, ok := artifact.(map[string]any)
if !ok {
problems = append(problems, "artifact entry is not an object")
continue
}
artifactPath := stringField(row, "path")
expectedHash := stringField(row, "sha256")
if artifactPath == "" || expectedHash == "" {
problems = append(problems, "artifact path or sha256 missing")
continue
}
allowedEntries[artifactPath] = true
if truthPackageForbiddenZipPath(artifactPath) {
problems = append(problems, "forbidden artifact path: "+artifactPath)
continue
}
entry := entries[artifactPath]
if entry == nil {
problems = append(problems, "artifact missing from ZIP: "+artifactPath)
continue
}
data, err := readZipFile(entry)
if err != nil {
problems = append(problems, "artifact read failed: "+artifactPath)
continue
}
computed := fmt.Sprintf("%x", sha256.Sum256(data))
if computed != expectedHash {
problems = append(problems, "artifact sha256 mismatch: "+artifactPath)
continue
}
verifiedArtifacts++
}
} else {
problems = append(problems, "truth package artifacts list missing")
}
for entryName := range entries {
if !allowedEntries[entryName] {
problems = append(problems, "unlisted ZIP entry: "+entryName)
}
}
return map[string]any{
"ok": len(problems) == 0,
"packageSha256": packageHash,
"manifestSha256": manifestHash,
"verifiedArtifacts": verifiedArtifacts,
"problems": problems,
}
}
func readZipFile(file *zip.File) ([]byte, error) {
reader, err := file.Open()
if err != nil {
return nil, err
}
defer reader.Close()
return io.ReadAll(reader)
}
func truthPackageForbiddenZipPath(path string) bool {
clean := filepath.Clean(path)
if path == "" ||
strings.HasPrefix(path, "/") ||
strings.Contains(path, "\\") ||
strings.Contains(path, ":") ||
strings.HasPrefix(path, "__MACOSX/") ||
strings.Contains(path, "/__MACOSX/") ||
strings.HasSuffix(path, ".DS_Store") ||
strings.HasPrefix(filepath.Base(path), "._") ||
strings.Contains(path, "sftp://") ||
strings.Contains(path, "/home/") ||
clean == "." ||
strings.HasPrefix(clean, "../") ||
clean == ".." {
return true
}
for _, segment := range strings.Split(path, "/") {
if segment == ".." {
return true
}
}
return false
}
func verifyDomainObject(domainKey string, obj attesto.M, payloadKey, camelHash, snakeHash string) map[string]any {
payload := objectField(obj, payloadKey)
hash := stringField(obj, camelHash, snakeHash)
computed, err := attesto.DomainHashHex(attesto.ProofstreamDomains[domainKey], payload)
ok := err == nil && computed == hash
problems := []string{}
if err != nil {
problems = append(problems, err.Error())
}
if computed != hash {
problems = append(problems, domainKey+" hash mismatch")
}
return map[string]any{"ok": ok, "computedHash": computed, "expectedHash": hash, "problems": problems}
}
func verifyQuorumObject(obj attesto.M) map[string]any {
accepted := numberField(obj, "acceptedWitnessCount", "accepted_witness_count", "witnessReceiptCount", "witness_receipt_count")
threshold := numberField(obj, "quorumThreshold", "quorum_threshold")
ok := threshold > 0 && accepted >= threshold
problems := []string{}
if threshold <= 0 {
problems = append(problems, "quorum threshold missing")
}
if accepted < threshold {
problems = append(problems, "quorum threshold not satisfied")
}
return map[string]any{"ok": ok, "acceptedWitnessCount": accepted, "quorumThreshold": threshold, "problems": problems}
}
func validateReadiness(kind, path string, obj attesto.M) map[string]any {
ok, _ := obj["ok"].(bool)
if !ok {
if summary, okSummary := obj["summary"].(map[string]any); okSummary {
if summaryOK, okBool := summary["ok"].(bool); okBool {
ok = summaryOK
}
}
}
problems := obj["problems"]
if problems == nil {
problems = []any{}
}
return map[string]any{"ok": ok, "kind": kind, "file": path, "problems": problems}
}
func defaultConfigPath(getenv func(string) string) string {
if value := getenv("ATTESTO_CONFIG"); value != "" {
return value
}
if value := getenv("XDG_CONFIG_HOME"); value != "" {
return filepath.Join(value, "attesto", "config.json")
}
if home := getenv("HOME"); home != "" {
return filepath.Join(home, ".config", "attesto", "config.json")
}
return "attesto-config.json"
}
func readConfig(path string) (cliConfig, error) {
var cfg cliConfig
raw, err := os.ReadFile(path)
if err != nil {
return cfg, err
}
return cfg, json.Unmarshal(raw, &cfg)
}
func writeConfig(path string, cfg cliConfig) error {
if err := os.MkdirAll(filepath.Dir(path), 0o700); err != nil {
return err
}
raw, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, append(raw, '\n'), 0o600)
}
func redactValue(value any) any {
raw, err := json.Marshal(value)
if err != nil {
return value
}
var decoded any
if err := json.Unmarshal(raw, &decoded); err != nil {
return value
}
return redactAny(decoded)
}
func redactAny(value any) any {
switch v := value.(type) {
case map[string]any:
out := make(map[string]any, len(v))
for key, child := range v {
lower := strings.ToLower(key)
if strings.Contains(lower, "secret") || strings.Contains(lower, "token") || strings.Contains(lower, "apikey") || strings.Contains(lower, "api_key") {
if s, ok := child.(string); ok && s != "" {
out[key] = mask(s)
continue
}
}
out[key] = redactAny(child)
}
return out
case []any:
out := make([]any, len(v))
for i, child := range v {
out[i] = redactAny(child)
}
return out
default:
return v
}
}
func redactMap(value map[string]any) map[string]any {
return redactAny(value).(map[string]any)
}
func sanitize(message string) string {
for _, marker := range []string{"sk_live_", "sk_test_", "pk_live_", "pk_test_", "npm_", "pypi-", "atto_live_", "atto_test_"} {
if strings.Contains(message, marker) {
return "redacted"
}
}
return message
}
func mask(secret string) string {
if len(secret) <= 8 {
return "redacted"
}
return secret[:4] + "..." + secret[len(secret)-4:]
}
func objectField(obj attesto.M, keys ...string) attesto.M {
for _, key := range keys {
if value, ok := obj[key].(map[string]any); ok {
return attesto.M(value)
}
}
return attesto.M{}
}
func stringField(obj attesto.M, keys ...string) string {
for _, key := range keys {
if value, ok := obj[key].(string); ok {
return value
}
}
return ""
}
func numberField(obj attesto.M, keys ...string) int {
for _, key := range keys {
switch value := obj[key].(type) {
case float64:
return int(value)
case int:
return value
case string:
parsed, _ := strconv.Atoi(value)
return parsed
}
}
return 0
}
func hmacEqual(a, b string) bool {
if len(a) != len(b) {
return false
}
var diff byte
for i := range a {
diff |= a[i] ^ b[i]
}
return diff == 0
}