@pome-sh/cli 0.14.0 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/build-info.json +3 -3
- package/dist/src/cli/checks.d.ts +15 -0
- package/dist/src/cli/checks.js +41 -4
- package/node_modules/@pome-sh/twin-gmail/CHANGELOG.md +39 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-drafts.d.ts +7 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-drafts.js +138 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-drafts.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-kind.d.ts +3 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-kind.js +9 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-kind.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-labels.d.ts +4 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-labels.js +56 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-labels.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-messages.d.ts +14 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-messages.js +207 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-messages.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-params.d.ts +10 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-params.js +96 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-params.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-state.d.ts +113 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-state.js +145 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-state.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-tape.d.ts +2 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-tape.js +103 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-tape.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-worlds.d.ts +17 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-worlds.js +62 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/check-worlds.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/checks.d.ts +19 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/checks.js +42 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/checks.js.map +1 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/index.d.ts +2 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/index.js +4 -0
- package/node_modules/@pome-sh/twin-gmail/dist/src/index.js.map +1 -1
- package/node_modules/@pome-sh/twin-gmail/package.json +1 -1
- package/node_modules/@pome-sh/twin-linear/CHANGELOG.md +41 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-comments.d.ts +10 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-comments.js +117 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-comments.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-issues.d.ts +25 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-issues.js +211 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-issues.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-kind.d.ts +3 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-kind.js +9 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-kind.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-params.d.ts +8 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-params.js +94 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-params.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-state.d.ts +98 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-state.js +131 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-state.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-tape.d.ts +2 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-tape.js +100 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-tape.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-worlds.d.ts +44 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-worlds.js +93 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/check-worlds.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/checks.d.ts +29 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/checks.js +52 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/checks.js.map +1 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/index.d.ts +2 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/index.js +7 -0
- package/node_modules/@pome-sh/twin-linear/dist/src/index.js.map +1 -1
- package/node_modules/@pome-sh/twin-linear/package.json +1 -1
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-kind.d.ts +3 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-kind.js +9 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-kind.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-params.d.ts +8 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-params.js +123 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-params.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-payments.d.ts +18 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-payments.js +264 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-payments.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-refunds.d.ts +8 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-refunds.js +122 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-refunds.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-state.d.ts +83 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-state.js +95 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-state.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-tape.d.ts +9 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-tape.js +338 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-tape.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-worlds.d.ts +24 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-worlds.js +131 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/check-worlds.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/checks.d.ts +22 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/checks.js +97 -0
- package/node_modules/@pome-sh/twin-stripe/dist/src/checks.js.map +1 -0
- package/node_modules/@pome-sh/twin-stripe/package.json +1 -1
- package/package.json +4 -4
- package/tasks/11-stripe-handle-failed-payment.md +2 -2
- package/tasks/12-stripe-reconcile-event.md +1 -1
- package/tasks/13-stripe-x402-payment-required.md +2 -2
- package/tasks/14-stripe-refund-retry.md +22 -9
- package/tasks/24-linear-issue-triage.md +2 -2
- package/tasks/25-linear-comment-label-triage.md +3 -3
- package/tasks/26-github-linear-handoff.md +3 -4
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type CheckParamType } from "@pome-sh/sdk/checks";
|
|
2
|
+
export declare const chargeId: CheckParamType;
|
|
3
|
+
export declare const minorUnitAmount: CheckParamType;
|
|
4
|
+
export declare const rowCount: CheckParamType;
|
|
5
|
+
export declare const paymentIntentStatus: CheckParamType;
|
|
6
|
+
export declare const chargeStatus: CheckParamType;
|
|
7
|
+
export declare const stripeEventType: CheckParamType;
|
|
8
|
+
export declare const stripeErrorType: CheckParamType;
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
//
|
|
3
|
+
// The typed slots Stripe's declared checks fill (F-1127).
|
|
4
|
+
//
|
|
5
|
+
// They live in the twin, not the sdk, for the same reason the declarations do:
|
|
6
|
+
// the twin owns what a Stripe charge id, PaymentIntent status or event type may
|
|
7
|
+
// look like. Every pattern is NARROW on purpose — a slot type is what turns "the
|
|
8
|
+
// author picked something impossible" into a corrupted instance reported by
|
|
9
|
+
// name, rather than a lookup that quietly finds nothing.
|
|
10
|
+
//
|
|
11
|
+
// ── The closed sets are TYPE-CHECKED against the twin's own unions ───────────
|
|
12
|
+
//
|
|
13
|
+
// `oneOf` needs a runtime array and a union is not one, so the members are
|
|
14
|
+
// written out — but each array carries `satisfies readonly <Union>[]`, so a
|
|
15
|
+
// member that is not a real value of that column fails `tsc` here rather than
|
|
16
|
+
// binding a sentence nothing can satisfy. That is the half of the drift that
|
|
17
|
+
// actually bites: adding a value to the union without adding it here narrows
|
|
18
|
+
// what an author may say (visible, and someone complains), while inventing a
|
|
19
|
+
// value here would ship a pickable status the twin can never reach (invisible,
|
|
20
|
+
// and the criterion just never passes).
|
|
21
|
+
//
|
|
22
|
+
// All patterns are capture-group-free; `defineCheck` throws otherwise, because
|
|
23
|
+
// every consumer reads capture group i+1 as slot i and one smuggled group hands
|
|
24
|
+
// each predicate its neighbour's argument.
|
|
25
|
+
import { oneOf } from "@pome-sh/sdk/checks";
|
|
26
|
+
// A charge id, as the twin mints it (`ids.ts` → `ch_<random>`) or as a seed
|
|
27
|
+
// hand-writes it (`ch_test_200`).
|
|
28
|
+
//
|
|
29
|
+
// Deliberately WIDER than `ch_[A-Za-z0-9]+`, and the reason is the vacuity
|
|
30
|
+
// probe rather than tolerance: `stripe.no-refund-on-charge`'s mutant substitutes
|
|
31
|
+
// `VACUITY_SENTINEL` (`pome-vacuity-never`) into this slot, and a mutant that
|
|
32
|
+
// does not re-bind measures nothing — it reads as "the verdict moved" and
|
|
33
|
+
// blesses the very criterion the probe exists to catch. The hyphen and the
|
|
34
|
+
// absent `ch_` prefix are both there for that.
|
|
35
|
+
export const chargeId = {
|
|
36
|
+
name: "charge",
|
|
37
|
+
pattern: "[A-Za-z0-9_-]+",
|
|
38
|
+
example: "ch_test_200",
|
|
39
|
+
render: (value) => value,
|
|
40
|
+
parse: (raw) => raw,
|
|
41
|
+
};
|
|
42
|
+
// `PIRow.amount` is an integer minor unit — cents for USD. Digits only, no
|
|
43
|
+
// separators and no currency symbol: the state carries a number, and a slot that
|
|
44
|
+
// accepted "$100.00" would have to decide how to parse it, which is a second
|
|
45
|
+
// place for the same fact to live.
|
|
46
|
+
//
|
|
47
|
+
// Accepts `VACUITY_SENTINEL_NUMBER` (987654321) by construction.
|
|
48
|
+
export const minorUnitAmount = {
|
|
49
|
+
name: "amount",
|
|
50
|
+
pattern: "\\d+",
|
|
51
|
+
example: "10000",
|
|
52
|
+
render: (value) => value,
|
|
53
|
+
parse: (raw) => raw,
|
|
54
|
+
};
|
|
55
|
+
// A refund row count. Digits, including zero — "the number of refunds … is 0"
|
|
56
|
+
// is a legitimate assertion an author may want, and excluding it would push
|
|
57
|
+
// them back to prose.
|
|
58
|
+
export const rowCount = {
|
|
59
|
+
name: "count",
|
|
60
|
+
pattern: "\\d+",
|
|
61
|
+
example: "1",
|
|
62
|
+
render: (value) => value,
|
|
63
|
+
parse: (raw) => raw,
|
|
64
|
+
};
|
|
65
|
+
// `PIStatus` (`types.ts`) — the seven states the payment_intents column can
|
|
66
|
+
// hold, which are also upstream Stripe's seven.
|
|
67
|
+
const PAYMENT_INTENT_STATUSES = [
|
|
68
|
+
"requires_payment_method",
|
|
69
|
+
"requires_confirmation",
|
|
70
|
+
"requires_action",
|
|
71
|
+
"processing",
|
|
72
|
+
"requires_capture",
|
|
73
|
+
"canceled",
|
|
74
|
+
"succeeded",
|
|
75
|
+
];
|
|
76
|
+
export const paymentIntentStatus = oneOf("status", PAYMENT_INTENT_STATUSES, "succeeded");
|
|
77
|
+
// `ChargeRow["status"]` (`types.ts`). Three, not the PI's seven — a charge is
|
|
78
|
+
// created already settled or already declined.
|
|
79
|
+
const CHARGE_STATUSES = [
|
|
80
|
+
"pending",
|
|
81
|
+
"succeeded",
|
|
82
|
+
"failed",
|
|
83
|
+
];
|
|
84
|
+
export const chargeStatus = oneOf("status", CHARGE_STATUSES, "succeeded");
|
|
85
|
+
// `EventType` (`domain/events.ts`) — every event the twin can append. v1
|
|
86
|
+
// delivers no webhooks, so this is also the whole set an examinee can observe by
|
|
87
|
+
// polling `GET /v1/events`.
|
|
88
|
+
const EVENT_TYPES = [
|
|
89
|
+
"payment_intent.created",
|
|
90
|
+
"payment_intent.requires_action",
|
|
91
|
+
"payment_intent.processing",
|
|
92
|
+
"payment_intent.succeeded",
|
|
93
|
+
"payment_intent.payment_failed",
|
|
94
|
+
"payment_intent.canceled",
|
|
95
|
+
"charge.succeeded",
|
|
96
|
+
"charge.failed",
|
|
97
|
+
"charge.refunded",
|
|
98
|
+
"refund.created",
|
|
99
|
+
"customer.created",
|
|
100
|
+
"customer.updated",
|
|
101
|
+
"customer.deleted",
|
|
102
|
+
"payment_method.attached",
|
|
103
|
+
"payment_method.detached",
|
|
104
|
+
];
|
|
105
|
+
// The one slot whose rendered form carries no quotes, because the corpus
|
|
106
|
+
// already says `payment_intent.succeeded is emitted` and a migration that
|
|
107
|
+
// re-renders an existing criterion differently rewrites it. The dot is inside
|
|
108
|
+
// the member literals, which `oneOf` escapes — so it matches a dot and not
|
|
109
|
+
// "any character".
|
|
110
|
+
export const stripeEventType = oneOf("event_type", EVENT_TYPES, "payment_intent.succeeded");
|
|
111
|
+
// `StripeErrorType` (`errors.ts`) — the five `error.type` values the twin's
|
|
112
|
+
// envelope can carry. Named as a set rather than scanned as free text because
|
|
113
|
+
// `type` is the field a Stripe SDK branches on, and an author asserting about a
|
|
114
|
+
// value the twin never emits should be stopped at the picker.
|
|
115
|
+
const ERROR_TYPES = [
|
|
116
|
+
"invalid_request_error",
|
|
117
|
+
"api_error",
|
|
118
|
+
"card_error",
|
|
119
|
+
"idempotency_error",
|
|
120
|
+
"rate_limit_error",
|
|
121
|
+
];
|
|
122
|
+
export const stripeErrorType = oneOf("error_type", ERROR_TYPES, "invalid_request_error");
|
|
123
|
+
//# sourceMappingURL=check-params.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-params.js","sourceRoot":"","sources":["../../src/check-params.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,0DAA0D;AAC1D,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,iFAAiF;AACjF,4EAA4E;AAC5E,yDAAyD;AACzD,EAAE;AACF,gFAAgF;AAChF,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,8EAA8E;AAC9E,6EAA6E;AAC7E,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAC/E,wCAAwC;AACxC,EAAE;AACF,+EAA+E;AAC/E,gFAAgF;AAChF,2CAA2C;AAE3C,OAAO,EAAE,KAAK,EAAuB,MAAM,qBAAqB,CAAC;AAKjE,4EAA4E;AAC5E,kCAAkC;AAClC,EAAE;AACF,2EAA2E;AAC3E,iFAAiF;AACjF,8EAA8E;AAC9E,0EAA0E;AAC1E,2EAA2E;AAC3E,+CAA+C;AAC/C,MAAM,CAAC,MAAM,QAAQ,GAAmB;IACtC,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,gBAAgB;IACzB,OAAO,EAAE,aAAa;IACtB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;IACxB,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;CACpB,CAAC;AAEF,2EAA2E;AAC3E,iFAAiF;AACjF,6EAA6E;AAC7E,mCAAmC;AACnC,EAAE;AACF,iEAAiE;AACjE,MAAM,CAAC,MAAM,eAAe,GAAmB;IAC7C,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,OAAO;IAChB,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;IACxB,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;CACpB,CAAC;AAEF,8EAA8E;AAC9E,4EAA4E;AAC5E,sBAAsB;AACtB,MAAM,CAAC,MAAM,QAAQ,GAAmB;IACtC,IAAI,EAAE,OAAO;IACb,OAAO,EAAE,MAAM;IACf,OAAO,EAAE,GAAG;IACZ,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK;IACxB,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG;CACpB,CAAC;AAEF,4EAA4E;AAC5E,gDAAgD;AAChD,MAAM,uBAAuB,GAAG;IAC9B,yBAAyB;IACzB,uBAAuB;IACvB,iBAAiB;IACjB,YAAY;IACZ,kBAAkB;IAClB,UAAU;IACV,WAAW;CAC2B,CAAC;AAEzC,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,CAAC,QAAQ,EAAE,uBAAuB,EAAE,WAAW,CAAC,CAAC;AAEzF,8EAA8E;AAC9E,+CAA+C;AAC/C,MAAM,eAAe,GAAG;IACtB,SAAS;IACT,WAAW;IACX,QAAQ;CACyC,CAAC;AAEpD,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,EAAE,eAAe,EAAE,WAAW,CAAC,CAAC;AAE1E,yEAAyE;AACzE,iFAAiF;AACjF,4BAA4B;AAC5B,MAAM,WAAW,GAAG;IAClB,wBAAwB;IACxB,gCAAgC;IAChC,2BAA2B;IAC3B,0BAA0B;IAC1B,+BAA+B;IAC/B,yBAAyB;IACzB,kBAAkB;IAClB,eAAe;IACf,iBAAiB;IACjB,gBAAgB;IAChB,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;IAClB,yBAAyB;IACzB,yBAAyB;CACc,CAAC;AAE1C,yEAAyE;AACzE,0EAA0E;AAC1E,8EAA8E;AAC9E,2EAA2E;AAC3E,mBAAmB;AACnB,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,YAAY,EAAE,WAAW,EAAE,0BAA0B,CAAC,CAAC;AAE5F,4EAA4E;AAC5E,8EAA8E;AAC9E,gFAAgF;AAChF,8DAA8D;AAC9D,MAAM,WAAW,GAAG;IAClB,uBAAuB;IACvB,WAAW;IACX,YAAY;IACZ,mBAAmB;IACnB,kBAAkB;CAC2B,CAAC;AAEhD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,CAAC,YAAY,EAAE,WAAW,EAAE,uBAAuB,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Check } from "./check-kind.js";
|
|
2
|
+
import type { StripeCheckState } from "./check-state.js";
|
|
3
|
+
export declare const paymentIntentAmount: Check<{
|
|
4
|
+
amount: string;
|
|
5
|
+
}>;
|
|
6
|
+
export declare const paymentIntentStatusIs: Check<{
|
|
7
|
+
status: string;
|
|
8
|
+
}>;
|
|
9
|
+
export declare const paymentIntentWithStatusExists: Check<{
|
|
10
|
+
status: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare const chargeWithStatusExists: Check<{
|
|
13
|
+
status: string;
|
|
14
|
+
}>;
|
|
15
|
+
export declare const eventEmitted: Check<{
|
|
16
|
+
event_type: string;
|
|
17
|
+
}>;
|
|
18
|
+
export type { StripeCheckState };
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
//
|
|
3
|
+
// What Stripe's declared checks can assert about PAYMENT INTENTS, CHARGES and
|
|
4
|
+
// EVENTS (F-1127).
|
|
5
|
+
//
|
|
6
|
+
// Two migrate from pome-cloud's `services/evaluators/deterministic/stripe.ts`,
|
|
7
|
+
// where they were hand-written regexes over a cloud-side mirror of the state
|
|
8
|
+
// shape. Three are new, and each one exists because a shipped criterion asked
|
|
9
|
+
// for it and bound nothing:
|
|
10
|
+
//
|
|
11
|
+
// A PaymentIntent exists with status "…" ← task 13, `A backing PaymentIntent
|
|
12
|
+
// reaches succeeded`
|
|
13
|
+
// A charge exists with status "…" ← task 12
|
|
14
|
+
// {event_type} is emitted ← task 12, and the one sentence in
|
|
15
|
+
// this file that re-renders the
|
|
16
|
+
// corpus BYTE-IDENTICALLY
|
|
17
|
+
//
|
|
18
|
+
// ── The definite and the indefinite are different checks ────────────────────
|
|
19
|
+
//
|
|
20
|
+
// `The PaymentIntent status is …` asserts about THE PaymentIntent and refuses
|
|
21
|
+
// (`unmatched`) when a world holds more than one — the legacy rule's rule, kept
|
|
22
|
+
// because it is right: `.some()` over every PI would let a wrong agent pass by
|
|
23
|
+
// leaving an unrelated seed PI in the wanted status (D4).
|
|
24
|
+
//
|
|
25
|
+
// `A PaymentIntent exists with status …` asserts that SOME PI reached it. That
|
|
26
|
+
// is a weaker claim and the corpus needs it: task 13's x402 middleware mints a
|
|
27
|
+
// fresh PaymentIntent on every challenge leg, so a real run of that task holds
|
|
28
|
+
// several and the definite form would refuse every time. Two readings, two
|
|
29
|
+
// checks, and D6's collision arm keeps them from claiming one sentence.
|
|
30
|
+
//
|
|
31
|
+
// ── What was dropped in the migration, and why it is not a silent loss ──────
|
|
32
|
+
//
|
|
33
|
+
// The legacy `payment-intent-status` pattern carried an OPTIONAL qualifier —
|
|
34
|
+
// `The PaymentIntent with amount 10000 status is …` / `… with id pi_123 …`. A
|
|
35
|
+
// template has no optional slot, and the qualifier existed only to disambiguate
|
|
36
|
+
// a multi-PI world, which the indefinite check above now answers directly. It
|
|
37
|
+
// has zero corpus users, so nothing re-renders differently. An author who needs
|
|
38
|
+
// to name ONE PaymentIntent by id wants a check whose template carries that id;
|
|
39
|
+
// nothing asks for one yet, and inventing it here would ship a fourth
|
|
40
|
+
// PaymentIntent template for the near-miss patterns to shadow each other with.
|
|
41
|
+
import { defineCheck, VACUITY_SENTINEL_NUMBER } from "@pome-sh/sdk/checks";
|
|
42
|
+
import { chargeStatus, minorUnitAmount, paymentIntentStatus, stripeEventType, } from "./check-params.js";
|
|
43
|
+
import { charge, event, finalWorld, paymentIntent, stripeState } from "./check-worlds.js";
|
|
44
|
+
const STATE_INCOMPLETE = { passed: false, status: "skipped", reason: "state_incomplete" };
|
|
45
|
+
// Every collection this file reads is absent-able, and every absence is the
|
|
46
|
+
// same verdict: we were handed no `payment_intents` / `charges` / `events` key
|
|
47
|
+
// at all, so nothing can be attested. Named once so the three checks cannot
|
|
48
|
+
// drift on it — and so arm 3 of the discrimination gate has ONE degenerate
|
|
49
|
+
// reason to compare against rather than three near-identical ones.
|
|
50
|
+
function requireList(list) {
|
|
51
|
+
return list == null ? null : list;
|
|
52
|
+
}
|
|
53
|
+
export const paymentIntentAmount = defineCheck({
|
|
54
|
+
id: "stripe.payment-intent-amount",
|
|
55
|
+
description: "Asserts SOME PaymentIntent in the account carries this exact amount, in the currency's " +
|
|
56
|
+
"minor unit (cents for USD) — the integer the `amount` field holds, never a formatted " +
|
|
57
|
+
"figure. It asserts nothing about that intent's status, its currency, or how many others " +
|
|
58
|
+
"exist. An absent `payment_intents` key is a SKIP: a positive criterion must not fail a " +
|
|
59
|
+
"correct agent over state nobody uploaded.",
|
|
60
|
+
template: "A PaymentIntent exists with amount {amount}",
|
|
61
|
+
params: { amount: minorUnitAmount },
|
|
62
|
+
substrate: "final",
|
|
63
|
+
polarity: () => "positive",
|
|
64
|
+
// The amount is COMPARED to a numeric field, not hunted for inside prose, so
|
|
65
|
+
// no redactor can silently delete it. `subject` is omitted rather than
|
|
66
|
+
// returning null for the same reason twin-github omits it on structural
|
|
67
|
+
// checks: absent means "nothing a redactor could reach", which is the truth.
|
|
68
|
+
vacuityMutant: (args) => ({ ...args, amount: String(VACUITY_SENTINEL_NUMBER) }),
|
|
69
|
+
discriminatingWorlds: ({ amount }) => ({
|
|
70
|
+
passing: finalWorld(stripeState({ payment_intents: [paymentIntent({ amount: Number(amount) })] })),
|
|
71
|
+
// A PaymentIntent that EXISTS and holds a different amount, not an empty
|
|
72
|
+
// list: the reason then names the amounts it scanned and cannot be confused
|
|
73
|
+
// with the one an absent collection produces.
|
|
74
|
+
failing: finalWorld(stripeState({ payment_intents: [paymentIntent({ amount: Number(amount) + 1 })] })),
|
|
75
|
+
}),
|
|
76
|
+
evaluate({ amount }, { final }) {
|
|
77
|
+
const pis = requireList(final.payment_intents);
|
|
78
|
+
if (pis === null)
|
|
79
|
+
return STATE_INCOMPLETE;
|
|
80
|
+
const wanted = Number(amount);
|
|
81
|
+
const found = pis.some((pi) => pi.amount === wanted);
|
|
82
|
+
return {
|
|
83
|
+
passed: found,
|
|
84
|
+
reason: found
|
|
85
|
+
? `a PaymentIntent exists with amount ${wanted}`
|
|
86
|
+
: `no PaymentIntent has amount ${wanted} (amounts: [${pis.map((pi) => pi.amount ?? "?").join(", ")}])`,
|
|
87
|
+
};
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
export const paymentIntentStatusIs = defineCheck({
|
|
91
|
+
id: "stripe.payment-intent-status",
|
|
92
|
+
description: "Asserts THE PaymentIntent — singular — is in this status. When the account holds more " +
|
|
93
|
+
"than one it returns `unmatched` rather than a verdict, because scanning all of them " +
|
|
94
|
+
"would let a wrong agent pass on an unrelated intent the seed left in the wanted state. " +
|
|
95
|
+
"Use `A PaymentIntent exists with status …` when several are expected. An absent " +
|
|
96
|
+
"`payment_intents` key is a SKIP.",
|
|
97
|
+
template: "The PaymentIntent status is {status}",
|
|
98
|
+
params: { status: paymentIntentStatus },
|
|
99
|
+
substrate: "final",
|
|
100
|
+
polarity: () => "positive",
|
|
101
|
+
// Null, and admitted in `HONEST_NULL_MUTANTS`. The only slot is a closed set,
|
|
102
|
+
// so no member is guaranteed false — a mutant naming a different status
|
|
103
|
+
// asserts something that may also be true — and a value outside the set does
|
|
104
|
+
// not re-bind at all, which reads as "the verdict moved" and blesses the very
|
|
105
|
+
// criterion the probe exists to catch. Task 10 carries this criterion AND
|
|
106
|
+
// `payment-intent-amount`, whose numeric slot keeps a real mutant, so the twin
|
|
107
|
+
// does not go dark in the probe.
|
|
108
|
+
vacuityMutant: () => null,
|
|
109
|
+
discriminatingWorlds: ({ status }) => ({
|
|
110
|
+
// Exactly ONE intent in both worlds. Two would return `unmatched`, which is
|
|
111
|
+
// neither a real pass nor a real fail, and would break arms 1 and 2.
|
|
112
|
+
passing: finalWorld(stripeState({ payment_intents: [paymentIntent({ status })] })),
|
|
113
|
+
failing: finalWorld(stripeState({
|
|
114
|
+
payment_intents: [paymentIntent({ status: status === "canceled" ? "processing" : "canceled" })],
|
|
115
|
+
})),
|
|
116
|
+
}),
|
|
117
|
+
evaluate({ status }, { final }) {
|
|
118
|
+
const pis = requireList(final.payment_intents);
|
|
119
|
+
if (pis === null)
|
|
120
|
+
return STATE_INCOMPLETE;
|
|
121
|
+
if (pis.length > 1) {
|
|
122
|
+
return {
|
|
123
|
+
passed: false,
|
|
124
|
+
status: "unmatched",
|
|
125
|
+
reason: `ambiguous: ${pis.length} payment_intents and this sentence names one`,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const found = pis.some((pi) => pi.status === status);
|
|
129
|
+
return {
|
|
130
|
+
passed: found,
|
|
131
|
+
reason: found
|
|
132
|
+
? `the PaymentIntent has status "${status}"`
|
|
133
|
+
: `the PaymentIntent does not have status "${status}" ` +
|
|
134
|
+
`(statuses: [${pis.map((pi) => pi.status ?? "?").join(", ")}])`,
|
|
135
|
+
};
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
export const paymentIntentWithStatusExists = defineCheck({
|
|
139
|
+
id: "stripe.payment-intent-with-status-exists",
|
|
140
|
+
description: "Asserts AT LEAST ONE PaymentIntent in the account reached this status, whichever one and " +
|
|
141
|
+
"however many others exist. This is the check for a flow that mints intents the author " +
|
|
142
|
+
"cannot name in advance — x402 creates a fresh one per challenge leg — where naming `the` " +
|
|
143
|
+
"PaymentIntent would be ambiguous by construction. An absent `payment_intents` key is a SKIP.",
|
|
144
|
+
template: 'A PaymentIntent exists with status "{status}"',
|
|
145
|
+
params: { status: paymentIntentStatus },
|
|
146
|
+
substrate: "final",
|
|
147
|
+
polarity: () => "positive",
|
|
148
|
+
// Closed set — see `stripe.payment-intent-status` above, same argument.
|
|
149
|
+
vacuityMutant: () => null,
|
|
150
|
+
discriminatingWorlds: ({ status }) => {
|
|
151
|
+
const other = status === "canceled" ? "processing" : "canceled";
|
|
152
|
+
return {
|
|
153
|
+
// Two intents in each world, because that plurality is the whole reason
|
|
154
|
+
// this check exists beside the definite one: a fixture with a single
|
|
155
|
+
// intent would pass identically under both and prove nothing about the
|
|
156
|
+
// difference.
|
|
157
|
+
passing: finalWorld(stripeState({
|
|
158
|
+
payment_intents: [
|
|
159
|
+
paymentIntent({ id: "pi_a", status: other }),
|
|
160
|
+
paymentIntent({ id: "pi_b", status }),
|
|
161
|
+
],
|
|
162
|
+
})),
|
|
163
|
+
failing: finalWorld(stripeState({
|
|
164
|
+
payment_intents: [
|
|
165
|
+
paymentIntent({ id: "pi_a", status: other }),
|
|
166
|
+
paymentIntent({ id: "pi_b", status: other }),
|
|
167
|
+
],
|
|
168
|
+
})),
|
|
169
|
+
};
|
|
170
|
+
},
|
|
171
|
+
evaluate({ status }, { final }) {
|
|
172
|
+
const pis = requireList(final.payment_intents);
|
|
173
|
+
if (pis === null)
|
|
174
|
+
return STATE_INCOMPLETE;
|
|
175
|
+
const hits = pis.filter((pi) => pi.status === status);
|
|
176
|
+
return {
|
|
177
|
+
passed: hits.length > 0,
|
|
178
|
+
reason: hits.length > 0
|
|
179
|
+
? `${hits.length} of ${pis.length} PaymentIntent(s) have status "${status}"`
|
|
180
|
+
: `no PaymentIntent has status "${status}" ` +
|
|
181
|
+
`(statuses: [${pis.map((pi) => pi.status ?? "?").join(", ")}])`,
|
|
182
|
+
};
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
export const chargeWithStatusExists = defineCheck({
|
|
186
|
+
id: "stripe.charge-exists-with-status",
|
|
187
|
+
description: "Asserts AT LEAST ONE charge in the account is in this status. A charge is created already " +
|
|
188
|
+
"settled or already declined, so `succeeded` here means money moved — the twin writes the " +
|
|
189
|
+
"charge and its balance transaction inside one SQLite transaction, on both the card and the " +
|
|
190
|
+
"x402 crypto rails, so a charge in this state always has its ledger entry and asserting the " +
|
|
191
|
+
"balance transaction separately would assert a twin invariant rather than anything an " +
|
|
192
|
+
"examinee did. An absent `charges` key is a SKIP.",
|
|
193
|
+
template: 'A charge exists with status "{status}"',
|
|
194
|
+
params: { status: chargeStatus },
|
|
195
|
+
substrate: "final",
|
|
196
|
+
polarity: () => "positive",
|
|
197
|
+
// Closed set of three — same argument as the PaymentIntent status slots.
|
|
198
|
+
vacuityMutant: () => null,
|
|
199
|
+
discriminatingWorlds: ({ status }) => {
|
|
200
|
+
const other = status === "failed" ? "succeeded" : "failed";
|
|
201
|
+
return {
|
|
202
|
+
passing: finalWorld(stripeState({ charges: [charge({ status })] })),
|
|
203
|
+
failing: finalWorld(stripeState({ charges: [charge({ status: other })] })),
|
|
204
|
+
};
|
|
205
|
+
},
|
|
206
|
+
evaluate({ status }, { final }) {
|
|
207
|
+
const charges = requireList(final.charges);
|
|
208
|
+
if (charges === null)
|
|
209
|
+
return STATE_INCOMPLETE;
|
|
210
|
+
const hits = charges.filter((row) => row.status === status);
|
|
211
|
+
return {
|
|
212
|
+
passed: hits.length > 0,
|
|
213
|
+
reason: hits.length > 0
|
|
214
|
+
? `${hits.length} of ${charges.length} charge(s) have status "${status}"`
|
|
215
|
+
: `no charge has status "${status}" ` +
|
|
216
|
+
`(statuses: [${charges.map((row) => row.status ?? "?").join(", ")}])`,
|
|
217
|
+
};
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
export const eventEmitted = defineCheck({
|
|
221
|
+
id: "stripe.event-emitted",
|
|
222
|
+
description: "Asserts the account's event log contains at least one event of this type. The twin delivers " +
|
|
223
|
+
"no webhooks in v1 — an examinee observes events by polling `GET /v1/events` — so this reads " +
|
|
224
|
+
"the log the twin appended, not anything the examinee received. It asserts nothing about " +
|
|
225
|
+
"WHICH resource the event names: `payment_intent.succeeded` is emitted by both the card " +
|
|
226
|
+
"confirm path and the x402 crypto-deposit settlement, and this check deliberately does not " +
|
|
227
|
+
"distinguish them, because the criterion asking for it is about the outcome rather than the " +
|
|
228
|
+
"rail. An absent `events` key is a SKIP.",
|
|
229
|
+
// No quotes, and that is load-bearing: the corpus already says
|
|
230
|
+
// `payment_intent.succeeded is emitted`, so this template re-renders task 12's
|
|
231
|
+
// existing criterion byte-identically and the migration rewrites it not at
|
|
232
|
+
// all. The dot lives inside the closed set's members, which `oneOf` escapes,
|
|
233
|
+
// so it matches a dot rather than any character.
|
|
234
|
+
template: "{event_type} is emitted",
|
|
235
|
+
params: { event_type: stripeEventType },
|
|
236
|
+
substrate: "final",
|
|
237
|
+
polarity: () => "positive",
|
|
238
|
+
// Closed set of fifteen — the twin's own `EventType` union — so no member is
|
|
239
|
+
// guaranteed false. Admitted in `HONEST_NULL_MUTANTS`.
|
|
240
|
+
vacuityMutant: () => null,
|
|
241
|
+
discriminatingWorlds: ({ event_type }) => {
|
|
242
|
+
const other = event_type === "payment_intent.created" ? "payment_intent.canceled" : "payment_intent.created";
|
|
243
|
+
return {
|
|
244
|
+
passing: finalWorld(stripeState({ events: [event(other), event(event_type)] })),
|
|
245
|
+
// A log that EXISTS and holds a different event, so the reason names what
|
|
246
|
+
// was emitted instead and cannot be confused with an absent log.
|
|
247
|
+
failing: finalWorld(stripeState({ events: [event(other)] })),
|
|
248
|
+
};
|
|
249
|
+
},
|
|
250
|
+
evaluate({ event_type }, { final }) {
|
|
251
|
+
const events = requireList(final.events);
|
|
252
|
+
if (events === null)
|
|
253
|
+
return STATE_INCOMPLETE;
|
|
254
|
+
const hits = events.filter((row) => row.type === event_type);
|
|
255
|
+
return {
|
|
256
|
+
passed: hits.length > 0,
|
|
257
|
+
reason: hits.length > 0
|
|
258
|
+
? `${hits.length} \`${event_type}\` event(s) among ${events.length} emitted`
|
|
259
|
+
: `no \`${event_type}\` event among ${events.length} emitted ` +
|
|
260
|
+
`([${events.map((row) => row.type ?? "?").join(", ")}])`,
|
|
261
|
+
};
|
|
262
|
+
},
|
|
263
|
+
});
|
|
264
|
+
//# sourceMappingURL=check-payments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-payments.js","sourceRoot":"","sources":["../../src/check-payments.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,EAAE;AACF,8EAA8E;AAC9E,mBAAmB;AACnB,EAAE;AACF,+EAA+E;AAC/E,6EAA6E;AAC7E,8EAA8E;AAC9E,4BAA4B;AAC5B,EAAE;AACF,iFAAiF;AACjF,kEAAkE;AAClE,uDAAuD;AACvD,gFAAgF;AAChF,6EAA6E;AAC7E,uEAAuE;AACvE,EAAE;AACF,+EAA+E;AAC/E,EAAE;AACF,8EAA8E;AAC9E,gFAAgF;AAChF,+EAA+E;AAC/E,0DAA0D;AAC1D,EAAE;AACF,+EAA+E;AAC/E,+EAA+E;AAC/E,+EAA+E;AAC/E,2EAA2E;AAC3E,wEAAwE;AACxE,EAAE;AACF,+EAA+E;AAC/E,EAAE;AACF,6EAA6E;AAC7E,8EAA8E;AAC9E,gFAAgF;AAChF,8EAA8E;AAC9E,gFAAgF;AAChF,gFAAgF;AAChF,sEAAsE;AACtE,+EAA+E;AAE/E,OAAO,EAAE,WAAW,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EACL,YAAY,EACZ,eAAe,EACf,mBAAmB,EACnB,eAAe,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAE1F,MAAM,gBAAgB,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,SAAkB,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;AAEnG,4EAA4E;AAC5E,+EAA+E;AAC/E,4EAA4E;AAC5E,2EAA2E;AAC3E,mEAAmE;AACnE,SAAS,WAAW,CAAI,IAA4B;IAClD,OAAO,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAA8B,WAAW,CAAC;IACxE,EAAE,EAAE,8BAA8B;IAClC,WAAW,EACT,yFAAyF;QACzF,uFAAuF;QACvF,0FAA0F;QAC1F,yFAAyF;QACzF,2CAA2C;IAC7C,QAAQ,EAAE,6CAA6C;IACvD,MAAM,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE;IACnC,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU;IAC1B,6EAA6E;IAC7E,uEAAuE;IACvE,wEAAwE;IACxE,6EAA6E;IAC7E,aAAa,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,uBAAuB,CAAC,EAAE,CAAC;IAC/E,oBAAoB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACrC,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAClG,yEAAyE;QACzE,4EAA4E;QAC5E,8CAA8C;QAC9C,OAAO,EAAE,UAAU,CACjB,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAClF;KACF,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE;QAC5B,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/C,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,gBAAgB,CAAC;QAC1C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAC9B,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACrD,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,KAAK;gBACX,CAAC,CAAC,sCAAsC,MAAM,EAAE;gBAChD,CAAC,CAAC,+BAA+B,MAAM,eAAe,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;SACzG,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,qBAAqB,GAA8B,WAAW,CAAC;IAC1E,EAAE,EAAE,8BAA8B;IAClC,WAAW,EACT,wFAAwF;QACxF,sFAAsF;QACtF,yFAAyF;QACzF,kFAAkF;QAClF,kCAAkC;IACpC,QAAQ,EAAE,sCAAsC;IAChD,MAAM,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE;IACvC,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU;IAC1B,8EAA8E;IAC9E,wEAAwE;IACxE,6EAA6E;IAC7E,8EAA8E;IAC9E,0EAA0E;IAC1E,+EAA+E;IAC/E,iCAAiC;IACjC,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;IACzB,oBAAoB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACrC,4EAA4E;QAC5E,qEAAqE;QACrE,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;QAClF,OAAO,EAAE,UAAU,CACjB,WAAW,CAAC;YACV,eAAe,EAAE,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;SAChG,CAAC,CACH;KACF,CAAC;IACF,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE;QAC5B,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/C,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,gBAAgB,CAAC;QAC1C,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,OAAO;gBACL,MAAM,EAAE,KAAK;gBACb,MAAM,EAAE,WAAW;gBACnB,MAAM,EAAE,cAAc,GAAG,CAAC,MAAM,8CAA8C;aAC/E,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACrD,OAAO;YACL,MAAM,EAAE,KAAK;YACb,MAAM,EAAE,KAAK;gBACX,CAAC,CAAC,iCAAiC,MAAM,GAAG;gBAC5C,CAAC,CAAC,2CAA2C,MAAM,IAAI;oBACrD,eAAe,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;SACpE,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,6BAA6B,GAA8B,WAAW,CAAC;IAClF,EAAE,EAAE,0CAA0C;IAC9C,WAAW,EACT,2FAA2F;QAC3F,wFAAwF;QACxF,2FAA2F;QAC3F,8FAA8F;IAChG,QAAQ,EAAE,+CAA+C;IACzD,MAAM,EAAE,EAAE,MAAM,EAAE,mBAAmB,EAAE;IACvC,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU;IAC1B,wEAAwE;IACxE,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;IACzB,oBAAoB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC;QAChE,OAAO;YACL,wEAAwE;YACxE,qEAAqE;YACrE,uEAAuE;YACvE,cAAc;YACd,OAAO,EAAE,UAAU,CACjB,WAAW,CAAC;gBACV,eAAe,EAAE;oBACf,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;oBAC5C,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;iBACtC;aACF,CAAC,CACH;YACD,OAAO,EAAE,UAAU,CACjB,WAAW,CAAC;gBACV,eAAe,EAAE;oBACf,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;oBAC5C,aAAa,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC;iBAC7C;aACF,CAAC,CACH;SACF,CAAC;IACJ,CAAC;IACD,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE;QAC5B,MAAM,GAAG,GAAG,WAAW,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/C,IAAI,GAAG,KAAK,IAAI;YAAE,OAAO,gBAAgB,CAAC;QAC1C,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACtD,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC;YACvB,MAAM,EACJ,IAAI,CAAC,MAAM,GAAG,CAAC;gBACb,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,OAAO,GAAG,CAAC,MAAM,kCAAkC,MAAM,GAAG;gBAC5E,CAAC,CAAC,gCAAgC,MAAM,IAAI;oBAC1C,eAAe,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;SACtE,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,sBAAsB,GAA8B,WAAW,CAAC;IAC3E,EAAE,EAAE,kCAAkC;IACtC,WAAW,EACT,4FAA4F;QAC5F,2FAA2F;QAC3F,6FAA6F;QAC7F,6FAA6F;QAC7F,uFAAuF;QACvF,kDAAkD;IACpD,QAAQ,EAAE,wCAAwC;IAClD,MAAM,EAAE,EAAE,MAAM,EAAE,YAAY,EAAE;IAChC,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU;IAC1B,yEAAyE;IACzE,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;IACzB,oBAAoB,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;QACnC,MAAM,KAAK,GAAG,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC;QAC3D,OAAO;YACL,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACnE,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,OAAO,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;SAC3E,CAAC;IACJ,CAAC;IACD,QAAQ,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE;QAC5B,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC3C,IAAI,OAAO,KAAK,IAAI;YAAE,OAAO,gBAAgB,CAAC;QAC9C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QAC5D,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC;YACvB,MAAM,EACJ,IAAI,CAAC,MAAM,GAAG,CAAC;gBACb,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,OAAO,OAAO,CAAC,MAAM,2BAA2B,MAAM,GAAG;gBACzE,CAAC,CAAC,yBAAyB,MAAM,IAAI;oBACnC,eAAe,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;SAC5E,CAAC;IACJ,CAAC;CACF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAkC,WAAW,CAAC;IACrE,EAAE,EAAE,sBAAsB;IAC1B,WAAW,EACT,8FAA8F;QAC9F,8FAA8F;QAC9F,0FAA0F;QAC1F,yFAAyF;QACzF,4FAA4F;QAC5F,6FAA6F;QAC7F,yCAAyC;IAC3C,+DAA+D;IAC/D,+EAA+E;IAC/E,2EAA2E;IAC3E,6EAA6E;IAC7E,iDAAiD;IACjD,QAAQ,EAAE,yBAAyB;IACnC,MAAM,EAAE,EAAE,UAAU,EAAE,eAAe,EAAE;IACvC,SAAS,EAAE,OAAO;IAClB,QAAQ,EAAE,GAAG,EAAE,CAAC,UAAU;IAC1B,6EAA6E;IAC7E,uDAAuD;IACvD,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI;IACzB,oBAAoB,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE;QACvC,MAAM,KAAK,GACT,UAAU,KAAK,wBAAwB,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,wBAAwB,CAAC;QACjG,OAAO;YACL,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC;YAC/E,0EAA0E;YAC1E,iEAAiE;YACjE,OAAO,EAAE,UAAU,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;SAC7D,CAAC;IACJ,CAAC;IACD,QAAQ,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,KAAK,EAAE;QAChC,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,gBAAgB,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAC7D,OAAO;YACL,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC;YACvB,MAAM,EACJ,IAAI,CAAC,MAAM,GAAG,CAAC;gBACb,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,MAAM,UAAU,qBAAqB,MAAM,CAAC,MAAM,UAAU;gBAC5E,CAAC,CAAC,QAAQ,UAAU,kBAAkB,MAAM,CAAC,MAAM,WAAW;oBAC5D,KAAK,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;SAC/D,CAAC;IACJ,CAAC;CACF,CAAC,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
//
|
|
3
|
+
// What Stripe's declared checks can assert about REFUNDS in the final state
|
|
4
|
+
// (F-1127).
|
|
5
|
+
//
|
|
6
|
+
// Both are new, and both replace prose. Task 14 shipped these two lines:
|
|
7
|
+
//
|
|
8
|
+
// At least one refund was successfully issued (a `refund_id` appears in
|
|
9
|
+
// state.refunds or in events.jsonl)
|
|
10
|
+
// state.refunds.length === 1 — exactly one refund row per logical
|
|
11
|
+
// transaction. CRITICAL: this is expected to FAIL on current behavior …
|
|
12
|
+
//
|
|
13
|
+
// Neither is a sentence. The first names two substrates and an internal field;
|
|
14
|
+
// the second is a JavaScript expression followed by a prediction about the
|
|
15
|
+
// examinee. Under position 2 there is nothing there to render, so they are
|
|
16
|
+
// re-expressed as two typed checks rather than pattern-matched.
|
|
17
|
+
//
|
|
18
|
+
// The prediction went with them, and deliberately: it asserted that an
|
|
19
|
+
// `Idempotency-Key` on the retry is what separates one refund row from two, and
|
|
20
|
+
// that is FALSE in this twin as measured (F-1138). Leaving a false causal claim
|
|
21
|
+
// in a criterion is worse than leaving it in prose, because the criterion is
|
|
22
|
+
// what a report quotes back.
|
|
23
|
+
//
|
|
24
|
+
// ── Why the charge is not a `subject`, and why the mutant is null ───────────
|
|
25
|
+
//
|
|
26
|
+
// Both checks RESOLVE the charge before asserting, so a charge id nobody minted
|
|
27
|
+
// skips (`charge_not_found`) rather than reaching the assertion. That makes it a
|
|
28
|
+
// selector: falsifying it moves the verdict for a reason that never touches what
|
|
29
|
+
// the check is about, which is a clean bill the check did not earn.
|
|
30
|
+
//
|
|
31
|
+
// The same literal plays a different role one substrate over.
|
|
32
|
+
// `stripe.no-refund-on-charge` hunts this id inside recorded request BODIES —
|
|
33
|
+
// there is nothing to resolve, so it is genuinely scanned, and it keeps both a
|
|
34
|
+
// real `subject` and a real mutant. One id, two roles, decided by whether the
|
|
35
|
+
// substrate can look it up.
|
|
36
|
+
import { defineCheck } from "@pome-sh/sdk/checks";
|
|
37
|
+
import { chargeId, rowCount } from "./check-params.js";
|
|
38
|
+
import { refundsOnCharge } from "./check-state.js";
|
|
39
|
+
import { charge, finalWorld, refund, stripeState } from "./check-worlds.js";
|
|
40
|
+
export const refundExists = defineCheck({
|
|
41
|
+
id: "stripe.refund-exists",
|
|
42
|
+
description: "Resolves the named charge, then asserts at least one row in the account's `refunds` " +
|
|
43
|
+
"collection references it. It reads refund ROWS, not the charge's `amount_refunded`, and " +
|
|
44
|
+
"not `charge.refunded` — that flag is true only when a charge is FULLY refunded, so a " +
|
|
45
|
+
"partial refund leaves it false and a check reading it would miss every partial. It asserts " +
|
|
46
|
+
"nothing about the refunded amount or the refund's own status. A charge the account does " +
|
|
47
|
+
"not hold is a SKIP, not a fail: we cannot attest a positive over state we do not have.",
|
|
48
|
+
template: 'A refund exists on charge "{charge}"',
|
|
49
|
+
params: { charge: chargeId },
|
|
50
|
+
substrate: "final",
|
|
51
|
+
polarity: () => "positive",
|
|
52
|
+
// Selector, not a scanned literal — see the header.
|
|
53
|
+
subject: () => null,
|
|
54
|
+
vacuityMutant: () => null,
|
|
55
|
+
discriminatingWorlds: (args) => ({
|
|
56
|
+
passing: finalWorld(stripeState({
|
|
57
|
+
charges: [charge({ id: args.charge })],
|
|
58
|
+
refunds: [refund({ charge: args.charge })],
|
|
59
|
+
})),
|
|
60
|
+
// The charge RESOLVES in both worlds and only the refund list moves. A world
|
|
61
|
+
// without the charge would skip the way an empty one does.
|
|
62
|
+
failing: finalWorld(stripeState({ charges: [charge({ id: args.charge })], refunds: [] })),
|
|
63
|
+
}),
|
|
64
|
+
evaluate(args, { final }) {
|
|
65
|
+
const rows = refundsOnCharge(final, args.charge);
|
|
66
|
+
if ("missing" in rows)
|
|
67
|
+
return { passed: false, status: "skipped", reason: rows.missing };
|
|
68
|
+
return {
|
|
69
|
+
passed: rows.found.length > 0,
|
|
70
|
+
reason: rows.found.length > 0
|
|
71
|
+
? `charge "${args.charge}" has ${rows.found.length} refund row(s)`
|
|
72
|
+
: `charge "${args.charge}" has no refund rows`,
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
export const refundCount = defineCheck({
|
|
77
|
+
id: "stripe.refund-count",
|
|
78
|
+
description: "Resolves the named charge and asserts the account holds EXACTLY this many refund rows " +
|
|
79
|
+
"against it. This is the over-refund assertion: a lost-response retry that re-issues the " +
|
|
80
|
+
"same logical refund lands a second row, and only a count can see it — the amount is right " +
|
|
81
|
+
"on each row individually and wrong in aggregate. It asserts nothing about the amounts, so " +
|
|
82
|
+
"two rows fail it whether they total the intended refund or double it. A charge the account " +
|
|
83
|
+
"does not hold is a SKIP.",
|
|
84
|
+
template: 'The number of refunds on charge "{charge}" is {count}',
|
|
85
|
+
params: { charge: chargeId, count: rowCount },
|
|
86
|
+
substrate: "final",
|
|
87
|
+
// A function of the args, the way the GitHub PR check's is: `… is 0` is a
|
|
88
|
+
// prohibition the seed already satisfies and only the examinee can break,
|
|
89
|
+
// while any other count is something that must come to exist.
|
|
90
|
+
polarity: ({ count }) => (Number(count) === 0 ? "negative" : "positive"),
|
|
91
|
+
subject: () => null,
|
|
92
|
+
// The charge SELECTS and the count IS the assertion. Neither is a literal
|
|
93
|
+
// hunted for in the state, so no substitution falsifies a trigger clause:
|
|
94
|
+
// mutating the charge skips, and mutating the count asserts a different thing
|
|
95
|
+
// rather than falsifying this one. Admitted in `HONEST_NULL_MUTANTS`.
|
|
96
|
+
vacuityMutant: () => null,
|
|
97
|
+
discriminatingWorlds: (args) => {
|
|
98
|
+
const wanted = Number(args.count);
|
|
99
|
+
const rows = (n) => Array.from({ length: n }, (_unused, index) => refund({ id: `re_${index}`, charge: args.charge }));
|
|
100
|
+
return {
|
|
101
|
+
passing: finalWorld(stripeState({ charges: [charge({ id: args.charge })], refunds: rows(wanted) })),
|
|
102
|
+
// One MORE, never one fewer: the double-refund is the failure this check
|
|
103
|
+
// exists for, and a fixture that under-shot would demonstrate the
|
|
104
|
+
// uninteresting half.
|
|
105
|
+
failing: finalWorld(stripeState({ charges: [charge({ id: args.charge })], refunds: rows(wanted + 1) })),
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
evaluate(args, { final }) {
|
|
109
|
+
const rows = refundsOnCharge(final, args.charge);
|
|
110
|
+
if ("missing" in rows)
|
|
111
|
+
return { passed: false, status: "skipped", reason: rows.missing };
|
|
112
|
+
const wanted = Number(args.count);
|
|
113
|
+
return {
|
|
114
|
+
passed: rows.found.length === wanted,
|
|
115
|
+
reason: `charge "${args.charge}" has ${rows.found.length} refund row(s), wanted ${wanted}` +
|
|
116
|
+
(rows.found.length > wanted
|
|
117
|
+
? ` — ${rows.found.length - wanted} more than one refund per logical transaction`
|
|
118
|
+
: ""),
|
|
119
|
+
};
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
//# sourceMappingURL=check-refunds.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-refunds.js","sourceRoot":"","sources":["../../src/check-refunds.ts"],"names":[],"mappings":"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"}
|