Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 47 additions & 18 deletions conformance/corpus/cases.json
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,23 @@
]
}
},
{
"id": "AgentAcceptance/signature/too_short",
"message": "AgentAcceptance",
"valid": false,
"rules": [
"string.min_len"
],
"json": {}
},
{
"id": "AgentAcceptance/valid",
"message": "AgentAcceptance",
"valid": true,
"json": {
"signature": "x"
}
},
{
"id": "AuthorizedExchange/relationship/not_in",
"message": "AuthorizedExchange",
Expand Down Expand Up @@ -1615,13 +1632,17 @@
],
"json": {
"idempotencyKey": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"offer": {
"offerId": "offer-seed",
"pricing": {
"model": "PRICING_MODEL_FREE",
"rate": "0"
"items": [
{
"offer": {
"offerId": "offer-seed",
"pricing": {
"model": "PRICING_MODEL_FREE",
"rate": "0"
}
}
}
}
]
}
},
{
Expand All @@ -1632,13 +1653,17 @@
"string.min_len"
],
"json": {
"offer": {
"offerId": "offer-seed",
"pricing": {
"model": "PRICING_MODEL_FREE",
"rate": "0"
"items": [
{
"offer": {
"offerId": "offer-seed",
"pricing": {
"model": "PRICING_MODEL_FREE",
"rate": "0"
}
}
}
}
]
}
},
{
Expand All @@ -1647,13 +1672,17 @@
"valid": true,
"json": {
"idempotencyKey": "idem-tx",
"offer": {
"offerId": "offer-seed",
"pricing": {
"model": "PRICING_MODEL_FREE",
"rate": "0"
"items": [
{
"offer": {
"offerId": "offer-seed",
"pricing": {
"model": "PRICING_MODEL_FREE",
"rate": "0"
}
}
}
}
]
}
},
{
Expand Down
11 changes: 0 additions & 11 deletions conformance/corpus/crossfield.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,5 @@
"ai-train"
]
}
},
{
"id": "TransactionRequest/cel/offer_xor_items",
"message": "TransactionRequest",
"valid": false,
"rules": [
"transaction_request.offer_xor_items"
],
"json": {
"idempotencyKey": "idem-tx"
}
}
]
15 changes: 6 additions & 9 deletions conformance/corpusgen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,12 @@ func seeds() map[string]proto.Message {
"LicenseTerm": &rampv1.LicenseTerm{Semantics: rampv1.TermSemantics_TERM_SEMANTICS_ENUMERATED, Pricing: pricing()},
"AcceptableRestriction": &rampv1.AcceptableRestriction{Axis: rampv1.RestrictionKind_RESTRICTION_KIND_FUNCTION, Values: []string{"ai-train"}},
"DisputeRequest": &rampv1.DisputeRequest{IdempotencyKey: "idem-dr", Reason: rampv1.DisputeReason_DISPUTE_REASON_CONTENT_MISMATCH},
// Reflected-Offer execute contract (RAMP-103): Offer is the required
// sub-message of TransactionItem (auto-fill needs its seed), and
// TransactionRequest needs a valid single-mode baseline because its
// offer_xor_items message-CEL rejects the empty auto-fill baseline.
// Reflected-Offer execute contract (RAMP-103 / items-only 6afpc): Offer is
// the required sub-message of TransactionItem (auto-fill needs its seed),
// and TransactionRequest needs a valid 1-item items[] baseline because its
// items field is now repeated.min_items=1 (single-offer mode removed).
"Offer": offer(),
"TransactionRequest": &rampv1.TransactionRequest{IdempotencyKey: "idem-tx", Offer: offer()},
"TransactionRequest": &rampv1.TransactionRequest{IdempotencyKey: "idem-tx", Items: []*rampv1.TransactionItem{{Offer: offer()}}},
}
}

Expand Down Expand Up @@ -152,7 +152,7 @@ func main() {
// verdict. This is kept SEPARATE from cases.json on purpose — cases.json is the
// FIELD-level corpus the generated Pydantic/Zod clients are tested against today,
// and those clients do not yet enforce cross-field CEL (the symmetric gap noted
// in ramp-sdk-api.md). The SDK L1 validator (ramphelpers.Validate) is tested
// in ramp-sdk-api.md). The SDK L1 validator (helpers.Validate) is tested
// against THIS file, and a future TS/Python L1 that authors the cross-field rules
// by hand consumes it as their oracle — without breaking the field-level parity.
func writeCrossField(v protovalidate.Validator) {
Expand Down Expand Up @@ -191,9 +191,6 @@ func writeCrossField(v protovalidate.Validator) {
},
},
"license_term.one_restriction_per_kind"},
{"TransactionRequest/cel/offer_xor_items",
&rampv1.TransactionRequest{IdempotencyKey: "idem-tx"},
"transaction_request.offer_xor_items"},
}

var cases []Case
Expand Down
1 change: 0 additions & 1 deletion conformance/descriptor_invariants_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ var zeroAllowed = map[string]string{
"OfferGroup.absence_reason": "output — set only when a group yields no offers",
"OfferGroup.discovery_method": "output — informational; how the group was discovered",
"DiscoveryResponse.absence_reason": "output — set only when the broker yields no offers; absent on success",
"TransactionResponse.delivery_method": "output — populated on a completed transaction",
"TransactionResultItem.delivery_method": "output — per-item delivery on a completed batch item",
"TransactionResultItem.denial_reason": "output — set only on a denied batch item",
"TransactionResultItem.restriction_mismatches": "output — axes a denied batch item failed",
Expand Down
1 change: 1 addition & 0 deletions conformance/reachability_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ var outOfBandRoots = map[string]string{
"WBAFile": "served at /.well-known/http-message-signatures-directory — the pure WBA JWK Set (identity keys + revocation_url)",
"ErrorDetail": "the transport-error envelope; carries the seven typed failure reasons",
"KeyRevocationList": "served key-revocation document (thumbprint list), fetched out of band from WBAFile.revocation_url",
"AgentAcceptancePayload": "canonical signing structure for AgentAcceptance (RAMP-102 §1); never sent on the wire — the signer and verifier deterministically marshal it to derive byte-identical signed bytes",
}

// refFields visits the message/enum each of md's fields references (following the
Expand Down
7 changes: 4 additions & 3 deletions conformance/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,9 +190,9 @@ func TestIdempotencyKeyRequired(t *testing.T) {

func idempotencyCases() []validationCase {
return []validationCase{
{"transaction empty key rejected", &rampv1.TransactionRequest{IdempotencyKey: ""}, false, "string.min_len"},
{"transaction key ok", &rampv1.TransactionRequest{IdempotencyKey: "idem-tx-1", Offer: &rampv1.Offer{OfferId: "of_1", Pricing: freePricing()}}, true, ""},
{"transaction neither offer nor items rejected", &rampv1.TransactionRequest{IdempotencyKey: "idem-tx-xor"}, false, "transaction_request.offer_xor_items"},
{"transaction empty key rejected", &rampv1.TransactionRequest{IdempotencyKey: "", Items: []*rampv1.TransactionItem{{Offer: &rampv1.Offer{OfferId: "of_1", Pricing: freePricing()}}}}, false, "string.min_len"},
{"transaction key ok", &rampv1.TransactionRequest{IdempotencyKey: "idem-tx-1", Items: []*rampv1.TransactionItem{{Offer: &rampv1.Offer{OfferId: "of_1", Pricing: freePricing()}}}}, true, ""},
{"transaction empty items rejected", &rampv1.TransactionRequest{IdempotencyKey: "idem-tx-empty"}, false, "repeated.min_items"},
{"usage report empty key rejected", &rampv1.UsageReport{IdempotencyKey: ""}, false, "string.min_len"},
{"usage report key ok", &rampv1.UsageReport{IdempotencyKey: "idem-ur-1"}, true, ""},
{"dispute empty key rejected", &rampv1.DisputeRequest{IdempotencyKey: "", Reason: rampv1.DisputeReason_DISPUTE_REASON_CONTENT_MISMATCH}, false, "string.min_len"},
Expand Down Expand Up @@ -260,6 +260,7 @@ var standardRuleIDs = map[string]bool{
"string.pattern": true,
"required": true,
"repeated.max_items": true,
"repeated.min_items": true,
"int64.gte": true,
"string.min_len": true,
"enum.not_in": true,
Expand Down
Binary file modified gen/descriptor.binpb
Binary file not shown.
Loading
Loading