fix(mcp): require xVerae- commercial key when EDGE_URL set; batch via edge
This commit is contained in:
parent
93c2548450
commit
13d1c5851b
2 changed files with 47 additions and 6 deletions
|
|
@ -21,8 +21,8 @@ type Client struct {
|
|||
Channel string
|
||||
}
|
||||
|
||||
// DefaultBaseURL is the public edge.
|
||||
const DefaultBaseURL = "https://zap.verae.ai"
|
||||
// DefaultBaseURL is the public commercial edge (non-Zapier).
|
||||
const DefaultBaseURL = "https://services.verae.ai"
|
||||
|
||||
// FromEnv builds a client when VERAE_MCP_EDGE_URL is set (non-empty).
|
||||
// Empty env disables edge billing (legacy direct VeraeTime only).
|
||||
|
|
|
|||
|
|
@ -30,6 +30,14 @@ func (d *Deps) resolveBearer(ctx context.Context, req *mcp.CallToolRequest) (str
|
|||
return authctx.Resolve(ctx, BearerFromRequest(req), d.RequireBearer, d.Keeper)
|
||||
}
|
||||
|
||||
// isCommercialEdgeKey reports tokens that edge apiKeyAuth can map to a prepaid customer.
|
||||
func isCommercialEdgeKey(tok string) bool {
|
||||
t := strings.TrimSpace(tok)
|
||||
return strings.HasPrefix(t, "xVerae-") ||
|
||||
strings.HasPrefix(t, "key-") ||
|
||||
strings.HasPrefix(t, "zmw_")
|
||||
}
|
||||
|
||||
func (d *Deps) stamp(ctx context.Context, req *mcp.CallToolRequest, in StampArgs) (*mcp.CallToolResult, ReceiptsOut, error) {
|
||||
if err := assertDigestArgs(req); err != nil {
|
||||
return nil, ReceiptsOut{}, err
|
||||
|
|
@ -49,8 +57,15 @@ func (d *Deps) stamp(ctx context.Context, req *mcp.CallToolRequest, in StampArgs
|
|||
if err != nil {
|
||||
return nil, ReceiptsOut{}, err
|
||||
}
|
||||
// Single commercial meter: when Edge is configured, bill via zap.verae.ai.
|
||||
// Single commercial meter: when Edge is configured, bill via services.verae.ai.
|
||||
// Caller must present a commercial key (xVerae- / key- / zmw_), not a bare chain JWT,
|
||||
// so settleStampBilling attributes the customer prepaid ledger.
|
||||
if d.Edge != nil {
|
||||
if !isCommercialEdgeKey(tok) {
|
||||
return nil, ReceiptsOut{}, fmt.Errorf(
|
||||
"commercial stamp requires portal API key (xVerae-… or key-…); get one at https://customer.verae.ai/portal/ — bare VeraeTime JWT is not billed on MCP when VERAE_MCP_EDGE_URL is set",
|
||||
)
|
||||
}
|
||||
if len(in.Metadata) > 0 || in.Restamp {
|
||||
return nil, ReceiptsOut{}, fmt.Errorf("metadata/restamp on edge-billed stamps is not supported yet; omit metadata or unset VERAE_MCP_EDGE_URL")
|
||||
}
|
||||
|
|
@ -121,13 +136,39 @@ func (d *Deps) stampBatch(ctx context.Context, req *mcp.CallToolRequest, in Stam
|
|||
}
|
||||
switch scope {
|
||||
case "global":
|
||||
if d.Global == nil {
|
||||
return nil, StampBatchOut{}, fmt.Errorf("global VeraeTime client not configured")
|
||||
}
|
||||
tok, err := d.writeBearer(ctx, req)
|
||||
if err != nil {
|
||||
return nil, StampBatchOut{}, err
|
||||
}
|
||||
// Prefer edge meter (per-digest) when configured — same prepaid path as single stamp.
|
||||
if d.Edge != nil {
|
||||
if !isCommercialEdgeKey(tok) {
|
||||
return nil, StampBatchOut{}, fmt.Errorf(
|
||||
"commercial stamp requires portal API key (xVerae-… or key-…); get one at https://customer.verae.ai/portal/",
|
||||
)
|
||||
}
|
||||
if len(in.Metadata) > 0 || in.Restamp {
|
||||
return nil, StampBatchOut{}, fmt.Errorf("metadata/restamp on edge-billed batch not supported yet")
|
||||
}
|
||||
out := StampBatchOut{Count: len(in.SHA256s)}
|
||||
for i, h := range in.SHA256s {
|
||||
it := BatchItemDTO{Index: i, Hash: h, Status: "submitted"}
|
||||
er, err := d.Edge.Stamp(ctx, h, tok)
|
||||
if err != nil {
|
||||
it.Status, it.Error = "failed", err.Error()
|
||||
out.Failed++
|
||||
} else {
|
||||
it.ReceiptID = er.ReceiptID
|
||||
it.Status = "completed"
|
||||
out.Created++
|
||||
}
|
||||
out.Items = append(out.Items, it)
|
||||
}
|
||||
return nil, out, nil
|
||||
}
|
||||
if d.Global == nil {
|
||||
return nil, StampBatchOut{}, fmt.Errorf("global VeraeTime client not configured")
|
||||
}
|
||||
var metas []veraetime.StampMeta
|
||||
if len(in.Metadata) > 0 || in.Restamp {
|
||||
if len(in.Metadata) > 0 && len(in.Metadata) != len(in.SHA256s) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue