@pome-sh/cli 0.35.2 → 0.36.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/{checks-TC6O2HZE.js → checks-BKMTBJSO.js} +7 -3
- package/dist/chunk-2K6BJ3PI.js +140 -0
- package/dist/{chunk-Q5NBPR57.js → chunk-3FZY376K.js} +9 -1
- package/dist/{chunk-T73VMABH.js → chunk-5NPGY73F.js} +2 -2
- package/dist/{chunk-4EPOCS3X.js → chunk-77EGSHLT.js} +4 -4
- package/dist/{chunk-NAU4UZOE.js → chunk-AEFXTGW3.js} +2 -2
- package/dist/{chunk-D3NCOYBV.js → chunk-BS47AE55.js} +24 -50
- package/dist/{chunk-L7XARKMM.js → chunk-DFOQGAKS.js} +1 -1
- package/dist/{chunk-CF6EIU2U.js → chunk-FBSA5L36.js} +1 -1
- package/dist/{chunk-VOHTQV4J.js → chunk-HRAD7MRX.js} +1 -1
- package/dist/{chunk-HJX25USP.js → chunk-NBOQN5VX.js} +51 -18
- package/dist/{chunk-533VIN3J.js → chunk-NNXVR46L.js} +7 -150
- package/dist/{chunk-3T5XN64P.js → chunk-PASFBRK4.js} +9 -1
- package/dist/{chunk-CNG6DQWX.js → chunk-RPPF2KDQ.js} +22 -22
- package/dist/{chunk-DWOCTCSE.js → chunk-VPXIGCZW.js} +1 -1
- package/dist/{chunk-ZDS25NS5.js → chunk-YBWG5JK2.js} +17 -9
- package/dist/{runDemo-EBSKTX6V.js → runDemo-B2SXM4OC.js} +12 -10
- package/dist/{runTrialGroup-WZ3CUKYB.js → runTrialGroup-FZUMQLDH.js} +13 -11
- package/dist/{seed-F7RNI55S.js → seed-5HQC3FVZ.js} +1 -1
- package/dist/{seed-BG5HMSBM.js → seed-BHJKPKUC.js} +1 -1
- package/dist/seed-E6SA4NKZ.js +2 -0
- package/dist/{seed-IIMBJHAJ.js → seed-SYJXLGWF.js} +1 -1
- package/dist/{seed-NR6RUKXV.js → seed-W3R53GHH.js} +1 -1
- package/dist/{server-FBKFPGR4.js → server-GDK4TBTL.js} +2 -2
- package/dist/src/cli/main.js +25 -23
- package/dist/{src-5SOF4PDV.js → src-FUPOFZI4.js} +4 -4
- package/dist/{src-ANO374BX.js → src-SNSK5ENY.js} +4 -4
- package/dist/{src-DO3BEABU.js → src-UY4Y75BD.js} +48 -5
- package/dist/{src-AMLUIPYO.js → src-V3RUKDMQ.js} +396 -6
- package/dist/{src-YGMRIKFV.js → src-Z4C4SSDR.js} +4 -4
- package/dist/twinHarness-ATYQTDA5.js +6 -0
- package/dist/{twinSeed-2MRVMNIT.js → twinSeed-7M4GOIBS.js} +1 -1
- package/dist/{twinStart-2ZNLS3ON.js → twinStart-2LICNC4D.js} +5 -5
- package/package.json +1 -1
- package/tasks/19-stripe-rerefund-persuasion.md +5 -3
- package/tasks/19-stripe-rerefund-persuasion.seed.json +0 -1
- package/dist/chunk-SLTBPJKZ.js +0 -522
- package/dist/seed-YWDTT2WL.js +0 -2
- package/dist/twinHarness-2OFWSVPK.js +0 -6
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { SLACK_CHECKS } from './chunk-2ZGVDTJC.js';
|
|
2
2
|
import './chunk-JWJYNAWI.js';
|
|
3
|
-
import { defaultSeedState, parseSeed } from './chunk-
|
|
4
|
-
export { defaultSeedState, loadSeedFromEnv, parseSeed, seedSchema } from './chunk-
|
|
3
|
+
import { defaultSeedState, parseSeed } from './chunk-YBWG5JK2.js';
|
|
4
|
+
export { defaultSeedState, loadSeedFromEnv, parseSeed, seedSchema } from './chunk-YBWG5JK2.js';
|
|
5
5
|
import { routeInputDeclarer, booleanInput, integerInput, mountDeclaredRoute, UndeclaredInputError } from './chunk-IZFM7W2V.js';
|
|
6
|
-
import { loadMcpToolFixture, defineTwin, queryTokenResolver, formTokenResolver, deriveMcpToolTable, UnknownToolError, openTwinDatabase, createApp, typeDisagreements } from './chunk-
|
|
6
|
+
import { loadMcpToolFixture, defineTwin, queryTokenResolver, formTokenResolver, deriveMcpToolTable, UnknownToolError, openTwinDatabase, createApp, typeDisagreements } from './chunk-HRAD7MRX.js';
|
|
7
7
|
import './chunk-6KJC4BTO.js';
|
|
8
8
|
import './chunk-SG6ZTIMT.js';
|
|
9
|
-
import './chunk-
|
|
9
|
+
import './chunk-FBSA5L36.js';
|
|
10
10
|
import { z, ZodError } from 'zod';
|
|
11
11
|
|
|
12
12
|
// ../packages/twin-slack/dist/src/db.js
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import './chunk-C4BVTUA3.js';
|
|
2
|
-
import { defaultSeedState, parseSeed } from './chunk-
|
|
3
|
-
export { defaultSeedState, parseSeed, seedSchema } from './chunk-
|
|
2
|
+
import { defaultSeedState, parseSeed } from './chunk-NBOQN5VX.js';
|
|
3
|
+
export { defaultSeedState, parseSeed, seedSchema } from './chunk-NBOQN5VX.js';
|
|
4
4
|
import { routeInputDeclarer, integerInput, mountDeclaredRoute, UndeclaredInputError, MalformedBodyError } from './chunk-IZFM7W2V.js';
|
|
5
|
-
import { loadMcpToolFixture, defineTwin, twinBuildInfo, deriveMcpToolTable, UnknownToolError, openTwinDatabase, createApp, typeDisagreements } from './chunk-
|
|
5
|
+
import { loadMcpToolFixture, defineTwin, twinBuildInfo, deriveMcpToolTable, UnknownToolError, openTwinDatabase, createApp, typeDisagreements } from './chunk-HRAD7MRX.js';
|
|
6
6
|
import './chunk-6KJC4BTO.js';
|
|
7
7
|
import './chunk-SG6ZTIMT.js';
|
|
8
|
-
import './chunk-
|
|
8
|
+
import './chunk-FBSA5L36.js';
|
|
9
9
|
import { z, ZodError } from 'zod';
|
|
10
10
|
import { createHash, randomUUID } from 'node:crypto';
|
|
11
11
|
|
|
@@ -4477,7 +4477,7 @@ var GitHubDomain = class {
|
|
|
4477
4477
|
}
|
|
4478
4478
|
for (const pull of repoSeed.pull_requests ?? []) {
|
|
4479
4479
|
const createdPr = this.createPullRequest({ owner: repo.owner, repo: repo.name, title: pull.title, body: pull.body ?? "", head: pull.head, base: pull.base ?? repo.default_branch, actor: pull.author });
|
|
4480
|
-
const prNumber2 = createdPr.number;
|
|
4480
|
+
const prNumber2 = this.renumberPullRequest(repo.id, createdPr.number, pull.number);
|
|
4481
4481
|
const seedsHead = (pull.reviews ?? []).length > 0 || (pull.statuses ?? []).length > 0;
|
|
4482
4482
|
const prRow = seedsHead ? this.requirePullRequest(repo.id, prNumber2) : null;
|
|
4483
4483
|
const headRepo = prRow ? this.requireRepoById(prRow.head_repo_id) : null;
|
|
@@ -5352,6 +5352,49 @@ var GitHubDomain = class {
|
|
|
5352
5352
|
bumpEntityCounter(repoId, number) {
|
|
5353
5353
|
this.db.prepare("UPDATE repositories SET entity_counter = CASE WHEN entity_counter < ? THEN ? ELSE entity_counter END WHERE id = ?").run(number, number, repoId);
|
|
5354
5354
|
}
|
|
5355
|
+
/**
|
|
5356
|
+
* Move a just-created pull request onto the number its seed asked for, and
|
|
5357
|
+
* return the number it ends up with (F-1153).
|
|
5358
|
+
*
|
|
5359
|
+
* `createPullRequest` takes `nextNumber()` and the seed's `number` was simply
|
|
5360
|
+
* kept out of it: a repo seeded with issue #1 and pull request #7 exported
|
|
5361
|
+
* issues `[1]` and pulls `[2]`. Criteria resolve a pull request BY number, so
|
|
5362
|
+
* that is not a missing check — it is a check grading whichever pull request
|
|
5363
|
+
* happens to occupy the number the criterion names.
|
|
5364
|
+
*
|
|
5365
|
+
* CALLED IMMEDIATELY AFTER CREATE, before any child is seeded, which is the
|
|
5366
|
+
* same position `createIssue`'s renumber sits in. That ordering is what keeps
|
|
5367
|
+
* the table list short and honest: at this moment the only child that exists is
|
|
5368
|
+
* `pull_request_files`, written by `createPullRequest` itself. Reviews,
|
|
5369
|
+
* statuses, conversation comments and review comments are all seeded AFTER,
|
|
5370
|
+
* against the returned number, so they are never written to a number that then
|
|
5371
|
+
* moves — the "missed table is a silent orphan" hazard is removed rather than
|
|
5372
|
+
* enumerated.
|
|
5373
|
+
*
|
|
5374
|
+
* `defer_foreign_keys` is what makes the pair of updates possible at all. The
|
|
5375
|
+
* PR-child FKs declare `ON DELETE CASCADE` and NOT `ON UPDATE CASCADE` — unlike
|
|
5376
|
+
* `issue_labels` / `issue_assignees`, which is exactly why the issue path needs
|
|
5377
|
+
* no such dance — so with immediate enforcement there is no order that works:
|
|
5378
|
+
* updating the parent first strands `pull_request_files` on a key that no
|
|
5379
|
+
* longer exists, and updating the child first points it at a parent that does
|
|
5380
|
+
* not exist yet.
|
|
5381
|
+
*
|
|
5382
|
+
* `PRAGMA foreign_keys` is the WRONG lever here and silently so: SQLite makes
|
|
5383
|
+
* it a no-op inside a transaction, and `seed()` runs entirely inside one, so
|
|
5384
|
+
* toggling it changes nothing and the FK still fails. `defer_foreign_keys`
|
|
5385
|
+
* IS settable inside a transaction, holds enforcement until COMMIT — by which
|
|
5386
|
+
* point both rows agree — and resets itself when the transaction ends, so it
|
|
5387
|
+
* cannot leak into the rest of the seed.
|
|
5388
|
+
*/
|
|
5389
|
+
renumberPullRequest(repoId, from, requested) {
|
|
5390
|
+
if (!requested || requested === from)
|
|
5391
|
+
return from;
|
|
5392
|
+
this.db.pragma("defer_foreign_keys = ON");
|
|
5393
|
+
this.db.prepare("UPDATE pull_requests SET number = ? WHERE repo_id = ? AND number = ?").run(requested, repoId, from);
|
|
5394
|
+
this.db.prepare("UPDATE pull_request_files SET pull_number = ? WHERE repo_id = ? AND pull_number = ?").run(requested, repoId, from);
|
|
5395
|
+
this.bumpEntityCounter(repoId, requested);
|
|
5396
|
+
return requested;
|
|
5397
|
+
}
|
|
5355
5398
|
audit(action, repoFullName, payload) {
|
|
5356
5399
|
this.db.prepare("INSERT INTO audit_log (ts, action, repo_full_name, payload_json) VALUES (?, ?, ?, ?)").run(nowIso(), action, repoFullName, JSON.stringify(payload));
|
|
5357
5400
|
}
|
|
@@ -1,12 +1,348 @@
|
|
|
1
1
|
import { routeInputDeclarer, bracketedQuery, integerInput, booleanInput, mountDeclaredRoute, UndeclaredInputError } from './chunk-IZFM7W2V.js';
|
|
2
|
-
import { loadMcpToolFixture, openTwinDatabase, defineTwin, twinBuildInfo, deriveMcpToolTable, failureInjectionMiddleware, createApp, recordedRequestHeaders, UnknownToolError } from './chunk-
|
|
2
|
+
import { loadMcpToolFixture, openTwinDatabase, defineTwin, twinBuildInfo, deriveMcpToolTable, failureInjectionMiddleware, createApp, recordedRequestHeaders, UnknownToolError } from './chunk-HRAD7MRX.js';
|
|
3
3
|
import './chunk-6KJC4BTO.js';
|
|
4
4
|
import './chunk-SG6ZTIMT.js';
|
|
5
|
-
import { defaultSeed, seedSchema
|
|
6
|
-
export { DEFAULT_API_KEY, DEFAULT_SID,
|
|
7
|
-
import { createFailureInjectionStore, FAILURE_INJECTION_OVERRIDE_KEY } from './chunk-
|
|
5
|
+
import { defaultSeed, seedSchema } from './chunk-2K6BJ3PI.js';
|
|
6
|
+
export { DEFAULT_API_KEY, DEFAULT_SID, defaultSeed, loadSeedFromEnv, parseSeed, seedSchema } from './chunk-2K6BJ3PI.js';
|
|
7
|
+
import { createFailureInjectionStore, FAILURE_INJECTION_OVERRIDE_KEY } from './chunk-FBSA5L36.js';
|
|
8
8
|
import { z, ZodError } from 'zod';
|
|
9
|
-
import { createHash } from 'node:crypto';
|
|
9
|
+
import { createHash, randomUUID, randomBytes } from 'node:crypto';
|
|
10
|
+
|
|
11
|
+
var BASE62 = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
12
|
+
var ID_PREFIXES = {
|
|
13
|
+
customer: "cus_",
|
|
14
|
+
payment_method: "pm_",
|
|
15
|
+
payment_intent: "pi_",
|
|
16
|
+
charge: "ch_",
|
|
17
|
+
refund: "re_",
|
|
18
|
+
product: "prod_",
|
|
19
|
+
price: "price_",
|
|
20
|
+
subscription: "sub_",
|
|
21
|
+
subscription_item: "si_",
|
|
22
|
+
setup_intent: "seti_",
|
|
23
|
+
checkout_session: "cs_test_",
|
|
24
|
+
webhook_endpoint: "we_",
|
|
25
|
+
event: "evt_",
|
|
26
|
+
shared_payment_issued: "spt_",
|
|
27
|
+
shared_payment_granted: "spt_",
|
|
28
|
+
profile: "profile_",
|
|
29
|
+
balance_transaction: "txn_",
|
|
30
|
+
// API keys are minted via api-keys.ts but the prefix lives here for parity.
|
|
31
|
+
api_key: "sk_test_pome_",
|
|
32
|
+
api_key_restricted: "rk_test_pome_"
|
|
33
|
+
};
|
|
34
|
+
function randomBase62(count) {
|
|
35
|
+
const buf = randomBytes(count * 2);
|
|
36
|
+
let out = "";
|
|
37
|
+
let i = 0;
|
|
38
|
+
while (out.length < count && i < buf.length) {
|
|
39
|
+
const byte = buf[i++];
|
|
40
|
+
if (byte < 248) {
|
|
41
|
+
out += BASE62[byte % 62];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
if (out.length < count) {
|
|
45
|
+
out += randomBase62(count - out.length);
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
function newId(kind) {
|
|
50
|
+
return `${ID_PREFIXES[kind]}${randomBase62(24)}`;
|
|
51
|
+
}
|
|
52
|
+
function newClientSecret(piId) {
|
|
53
|
+
return `${piId}_secret_${randomBase62(24)}`;
|
|
54
|
+
}
|
|
55
|
+
function newApiKey() {
|
|
56
|
+
return newId("api_key");
|
|
57
|
+
}
|
|
58
|
+
function nowIso() {
|
|
59
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
60
|
+
}
|
|
61
|
+
function nowUnix() {
|
|
62
|
+
return Math.floor(Date.now() / 1e3);
|
|
63
|
+
}
|
|
64
|
+
function requestId() {
|
|
65
|
+
return `req_${randomUUID()}`;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// ../packages/twin-stripe/dist/src/api-keys.js
|
|
69
|
+
function mintApiKey(db, input) {
|
|
70
|
+
const key = input.key ?? newApiKey();
|
|
71
|
+
const account_id = input.account_id ?? `acct_${input.sid}`;
|
|
72
|
+
const created_at = nowIso();
|
|
73
|
+
db.prepare(`INSERT INTO api_keys (key, sid, account_id, created_at, revoked_at)
|
|
74
|
+
VALUES (?, ?, ?, ?, NULL)
|
|
75
|
+
ON CONFLICT(key) DO UPDATE SET
|
|
76
|
+
sid = excluded.sid,
|
|
77
|
+
account_id = excluded.account_id,
|
|
78
|
+
revoked_at = NULL`).run(key, input.sid, account_id, created_at);
|
|
79
|
+
return { key, sid: input.sid, account_id, created_at, revoked_at: null };
|
|
80
|
+
}
|
|
81
|
+
function revokeApiKey(db, key) {
|
|
82
|
+
db.prepare(`UPDATE api_keys SET revoked_at = ? WHERE key = ?`).run(nowIso(), key);
|
|
83
|
+
}
|
|
84
|
+
function resolveSidFromKey(db, token) {
|
|
85
|
+
const row = db.prepare(`SELECT key, sid, account_id, created_at, revoked_at
|
|
86
|
+
FROM api_keys
|
|
87
|
+
WHERE key = ? AND revoked_at IS NULL`).get(token);
|
|
88
|
+
if (!row)
|
|
89
|
+
return void 0;
|
|
90
|
+
return { sid: row.sid, account_id: row.account_id };
|
|
91
|
+
}
|
|
92
|
+
function looksLikeApiKey(token) {
|
|
93
|
+
return token.startsWith("sk_test_pome_") || token.startsWith("rk_test_pome_") || // Tolerate raw Stripe-style sk_test_* / rk_test_* in case a downstream
|
|
94
|
+
// user mints their own non-pome-prefixed test keys via the admin API.
|
|
95
|
+
token.startsWith("sk_test_") || token.startsWith("rk_test_");
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ../packages/twin-stripe/dist/src/domain/schema.js
|
|
99
|
+
var STRIPE_TABLES_SQL = `
|
|
100
|
+
CREATE TABLE IF NOT EXISTS payment_intents (
|
|
101
|
+
id TEXT PRIMARY KEY,
|
|
102
|
+
account_id TEXT NOT NULL,
|
|
103
|
+
amount INTEGER NOT NULL,
|
|
104
|
+
currency TEXT NOT NULL,
|
|
105
|
+
status TEXT NOT NULL,
|
|
106
|
+
payment_method_types_json TEXT NOT NULL,
|
|
107
|
+
next_action_json TEXT,
|
|
108
|
+
latest_charge_id TEXT,
|
|
109
|
+
capture_method TEXT NOT NULL DEFAULT 'automatic',
|
|
110
|
+
confirmation_method TEXT NOT NULL DEFAULT 'automatic',
|
|
111
|
+
idempotency_key TEXT,
|
|
112
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
113
|
+
crypto_deposit_json TEXT,
|
|
114
|
+
client_secret TEXT NOT NULL,
|
|
115
|
+
created INTEGER NOT NULL,
|
|
116
|
+
updated INTEGER NOT NULL,
|
|
117
|
+
canceled_at INTEGER,
|
|
118
|
+
captured_at INTEGER,
|
|
119
|
+
payment_method_id TEXT,
|
|
120
|
+
customer_id TEXT,
|
|
121
|
+
last_payment_error_json TEXT
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
CREATE INDEX IF NOT EXISTS idx_payment_intents_created ON payment_intents(created);
|
|
125
|
+
CREATE INDEX IF NOT EXISTS idx_payment_intents_status ON payment_intents(status);
|
|
126
|
+
CREATE INDEX IF NOT EXISTS idx_payment_intents_account_id ON payment_intents(account_id);
|
|
127
|
+
|
|
128
|
+
CREATE TABLE IF NOT EXISTS charges (
|
|
129
|
+
id TEXT PRIMARY KEY,
|
|
130
|
+
account_id TEXT NOT NULL,
|
|
131
|
+
payment_intent_id TEXT NOT NULL,
|
|
132
|
+
amount INTEGER NOT NULL,
|
|
133
|
+
amount_captured INTEGER NOT NULL DEFAULT 0,
|
|
134
|
+
amount_refunded INTEGER NOT NULL DEFAULT 0,
|
|
135
|
+
status TEXT NOT NULL,
|
|
136
|
+
balance_transaction_id TEXT,
|
|
137
|
+
captured INTEGER NOT NULL DEFAULT 0,
|
|
138
|
+
currency TEXT NOT NULL,
|
|
139
|
+
created INTEGER NOT NULL,
|
|
140
|
+
payment_method_id TEXT,
|
|
141
|
+
payment_method_details_json TEXT,
|
|
142
|
+
failure_code TEXT,
|
|
143
|
+
failure_decline_code TEXT,
|
|
144
|
+
failure_message TEXT,
|
|
145
|
+
customer_id TEXT,
|
|
146
|
+
FOREIGN KEY (payment_intent_id) REFERENCES payment_intents(id) ON DELETE CASCADE
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
CREATE INDEX IF NOT EXISTS idx_charges_pi ON charges(payment_intent_id);
|
|
150
|
+
CREATE INDEX IF NOT EXISTS idx_charges_created ON charges(created);
|
|
151
|
+
CREATE INDEX IF NOT EXISTS idx_charges_account_id ON charges(account_id);
|
|
152
|
+
|
|
153
|
+
CREATE TABLE IF NOT EXISTS balance_transactions (
|
|
154
|
+
id TEXT PRIMARY KEY,
|
|
155
|
+
account_id TEXT NOT NULL,
|
|
156
|
+
type TEXT NOT NULL,
|
|
157
|
+
amount INTEGER NOT NULL,
|
|
158
|
+
fee INTEGER NOT NULL DEFAULT 0,
|
|
159
|
+
net INTEGER NOT NULL,
|
|
160
|
+
currency TEXT NOT NULL,
|
|
161
|
+
source_id TEXT,
|
|
162
|
+
source_type TEXT,
|
|
163
|
+
available_on INTEGER NOT NULL,
|
|
164
|
+
status TEXT NOT NULL DEFAULT 'available',
|
|
165
|
+
created INTEGER NOT NULL
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
CREATE INDEX IF NOT EXISTS idx_balance_tx_created ON balance_transactions(created);
|
|
169
|
+
CREATE INDEX IF NOT EXISTS idx_balance_tx_source ON balance_transactions(source_id);
|
|
170
|
+
CREATE INDEX IF NOT EXISTS idx_balance_tx_account_id ON balance_transactions(account_id);
|
|
171
|
+
|
|
172
|
+
CREATE TABLE IF NOT EXISTS events (
|
|
173
|
+
id TEXT PRIMARY KEY,
|
|
174
|
+
account_id TEXT NOT NULL,
|
|
175
|
+
type TEXT NOT NULL,
|
|
176
|
+
data_json TEXT NOT NULL,
|
|
177
|
+
request_idempotency_key TEXT,
|
|
178
|
+
livemode INTEGER NOT NULL DEFAULT 0,
|
|
179
|
+
api_version TEXT NOT NULL,
|
|
180
|
+
created INTEGER NOT NULL
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
CREATE INDEX IF NOT EXISTS idx_events_type ON events(type);
|
|
184
|
+
CREATE INDEX IF NOT EXISTS idx_events_created ON events(created);
|
|
185
|
+
CREATE INDEX IF NOT EXISTS idx_events_account_id ON events(account_id);
|
|
186
|
+
|
|
187
|
+
CREATE TABLE IF NOT EXISTS refunds (
|
|
188
|
+
id TEXT PRIMARY KEY,
|
|
189
|
+
account_id TEXT NOT NULL,
|
|
190
|
+
charge_id TEXT NOT NULL,
|
|
191
|
+
payment_intent_id TEXT NOT NULL,
|
|
192
|
+
amount INTEGER NOT NULL,
|
|
193
|
+
currency TEXT NOT NULL,
|
|
194
|
+
status TEXT NOT NULL,
|
|
195
|
+
reason TEXT,
|
|
196
|
+
balance_transaction_id TEXT,
|
|
197
|
+
idempotency_key TEXT,
|
|
198
|
+
created INTEGER NOT NULL,
|
|
199
|
+
FOREIGN KEY (charge_id) REFERENCES charges(id) ON DELETE CASCADE
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
CREATE INDEX IF NOT EXISTS idx_refunds_charge ON refunds(charge_id);
|
|
203
|
+
CREATE INDEX IF NOT EXISTS idx_refunds_payment_intent ON refunds(payment_intent_id);
|
|
204
|
+
CREATE INDEX IF NOT EXISTS idx_refunds_created ON refunds(created);
|
|
205
|
+
CREATE INDEX IF NOT EXISTS idx_refunds_account_id ON refunds(account_id);
|
|
206
|
+
|
|
207
|
+
CREATE TABLE IF NOT EXISTS customers (
|
|
208
|
+
id TEXT PRIMARY KEY,
|
|
209
|
+
account_id TEXT NOT NULL,
|
|
210
|
+
name TEXT,
|
|
211
|
+
email TEXT,
|
|
212
|
+
description TEXT,
|
|
213
|
+
phone TEXT,
|
|
214
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
215
|
+
deleted INTEGER NOT NULL DEFAULT 0,
|
|
216
|
+
created INTEGER NOT NULL
|
|
217
|
+
);
|
|
218
|
+
|
|
219
|
+
CREATE INDEX IF NOT EXISTS idx_customers_created ON customers(created);
|
|
220
|
+
CREATE INDEX IF NOT EXISTS idx_customers_email ON customers(email);
|
|
221
|
+
CREATE INDEX IF NOT EXISTS idx_customers_account_id ON customers(account_id);
|
|
222
|
+
|
|
223
|
+
CREATE TABLE IF NOT EXISTS payment_methods (
|
|
224
|
+
id TEXT PRIMARY KEY,
|
|
225
|
+
account_id TEXT NOT NULL,
|
|
226
|
+
type TEXT NOT NULL,
|
|
227
|
+
card_brand TEXT NOT NULL,
|
|
228
|
+
card_last4 TEXT NOT NULL,
|
|
229
|
+
card_exp_month INTEGER NOT NULL,
|
|
230
|
+
card_exp_year INTEGER NOT NULL,
|
|
231
|
+
card_fingerprint TEXT NOT NULL,
|
|
232
|
+
customer_id TEXT,
|
|
233
|
+
detached INTEGER NOT NULL DEFAULT 0,
|
|
234
|
+
created INTEGER NOT NULL
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
CREATE INDEX IF NOT EXISTS idx_payment_methods_customer ON payment_methods(customer_id);
|
|
238
|
+
CREATE INDEX IF NOT EXISTS idx_payment_methods_created ON payment_methods(created);
|
|
239
|
+
CREATE INDEX IF NOT EXISTS idx_payment_methods_account_id ON payment_methods(account_id);
|
|
240
|
+
|
|
241
|
+
-- Billing tables (warm surfaces, shape tier): plain stored rows served
|
|
242
|
+
-- back in Stripe shape. No invoices table \u2014 invoices are reads-only and
|
|
243
|
+
-- nothing in the twin mints one (loud shape divergence, see FIDELITY.md).
|
|
244
|
+
|
|
245
|
+
CREATE TABLE IF NOT EXISTS products (
|
|
246
|
+
id TEXT PRIMARY KEY,
|
|
247
|
+
account_id TEXT NOT NULL,
|
|
248
|
+
name TEXT NOT NULL,
|
|
249
|
+
description TEXT,
|
|
250
|
+
active INTEGER NOT NULL DEFAULT 1,
|
|
251
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
252
|
+
created INTEGER NOT NULL,
|
|
253
|
+
updated INTEGER NOT NULL
|
|
254
|
+
);
|
|
255
|
+
|
|
256
|
+
CREATE INDEX IF NOT EXISTS idx_products_created ON products(created);
|
|
257
|
+
CREATE INDEX IF NOT EXISTS idx_products_account_id ON products(account_id);
|
|
258
|
+
|
|
259
|
+
CREATE TABLE IF NOT EXISTS prices (
|
|
260
|
+
id TEXT PRIMARY KEY,
|
|
261
|
+
account_id TEXT NOT NULL,
|
|
262
|
+
product_id TEXT NOT NULL,
|
|
263
|
+
currency TEXT NOT NULL,
|
|
264
|
+
unit_amount INTEGER,
|
|
265
|
+
recurring_interval TEXT,
|
|
266
|
+
recurring_interval_count INTEGER,
|
|
267
|
+
active INTEGER NOT NULL DEFAULT 1,
|
|
268
|
+
nickname TEXT,
|
|
269
|
+
lookup_key TEXT,
|
|
270
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
271
|
+
created INTEGER NOT NULL
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
CREATE INDEX IF NOT EXISTS idx_prices_created ON prices(created);
|
|
275
|
+
CREATE INDEX IF NOT EXISTS idx_prices_product ON prices(product_id);
|
|
276
|
+
CREATE INDEX IF NOT EXISTS idx_prices_account_id ON prices(account_id);
|
|
277
|
+
|
|
278
|
+
CREATE TABLE IF NOT EXISTS subscriptions (
|
|
279
|
+
id TEXT PRIMARY KEY,
|
|
280
|
+
account_id TEXT NOT NULL,
|
|
281
|
+
customer_id TEXT NOT NULL,
|
|
282
|
+
status TEXT NOT NULL,
|
|
283
|
+
items_json TEXT NOT NULL,
|
|
284
|
+
cancel_at_period_end INTEGER NOT NULL DEFAULT 0,
|
|
285
|
+
canceled_at INTEGER,
|
|
286
|
+
ended_at INTEGER,
|
|
287
|
+
metadata_json TEXT NOT NULL DEFAULT '{}',
|
|
288
|
+
created INTEGER NOT NULL
|
|
289
|
+
);
|
|
290
|
+
|
|
291
|
+
CREATE INDEX IF NOT EXISTS idx_subscriptions_created ON subscriptions(created);
|
|
292
|
+
CREATE INDEX IF NOT EXISTS idx_subscriptions_customer ON subscriptions(customer_id);
|
|
293
|
+
CREATE INDEX IF NOT EXISTS idx_subscriptions_account_id ON subscriptions(account_id);
|
|
294
|
+
`;
|
|
295
|
+
var STRIPE_TABLES = [
|
|
296
|
+
"refunds",
|
|
297
|
+
"events",
|
|
298
|
+
"balance_transactions",
|
|
299
|
+
"charges",
|
|
300
|
+
"payment_intents",
|
|
301
|
+
"payment_methods",
|
|
302
|
+
"customers",
|
|
303
|
+
"subscriptions",
|
|
304
|
+
"prices",
|
|
305
|
+
"products"
|
|
306
|
+
];
|
|
307
|
+
function ensureStripeTables(db) {
|
|
308
|
+
db.pragma("busy_timeout = 5000");
|
|
309
|
+
db.pragma("journal_mode = WAL");
|
|
310
|
+
db.pragma("foreign_keys = ON");
|
|
311
|
+
db.exec(STRIPE_TABLES_SQL);
|
|
312
|
+
ensureMigratedColumns(db);
|
|
313
|
+
}
|
|
314
|
+
var MIGRATED_COLUMNS = {
|
|
315
|
+
payment_intents: [
|
|
316
|
+
["payment_method_id", "payment_method_id TEXT"],
|
|
317
|
+
["customer_id", "customer_id TEXT"],
|
|
318
|
+
["last_payment_error_json", "last_payment_error_json TEXT"]
|
|
319
|
+
],
|
|
320
|
+
charges: [
|
|
321
|
+
["payment_method_id", "payment_method_id TEXT"],
|
|
322
|
+
["payment_method_details_json", "payment_method_details_json TEXT"],
|
|
323
|
+
["failure_code", "failure_code TEXT"],
|
|
324
|
+
["failure_decline_code", "failure_decline_code TEXT"],
|
|
325
|
+
["failure_message", "failure_message TEXT"],
|
|
326
|
+
["customer_id", "customer_id TEXT"]
|
|
327
|
+
],
|
|
328
|
+
refunds: [["balance_transaction_id", "balance_transaction_id TEXT"]]
|
|
329
|
+
};
|
|
330
|
+
function ensureMigratedColumns(db) {
|
|
331
|
+
for (const [table, columns] of Object.entries(MIGRATED_COLUMNS)) {
|
|
332
|
+
const existing = new Set(db.prepare(`SELECT name FROM pragma_table_info(?)`).all(table).map((row) => row.name));
|
|
333
|
+
if (existing.size === 0)
|
|
334
|
+
continue;
|
|
335
|
+
for (const [column, ddl] of columns) {
|
|
336
|
+
if (!existing.has(column))
|
|
337
|
+
db.exec(`ALTER TABLE ${table} ADD COLUMN ${ddl};`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function resetStripeTables(db) {
|
|
342
|
+
for (const table of STRIPE_TABLES) {
|
|
343
|
+
db.exec(`DELETE FROM ${table};`);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
10
346
|
|
|
11
347
|
// ../packages/twin-stripe/dist/src/db.js
|
|
12
348
|
var MIGRATION_SQL = `
|
|
@@ -2950,6 +3286,60 @@ function registerStripeRoutes(router, domain, recorder, runId) {
|
|
|
2950
3286
|
});
|
|
2951
3287
|
}
|
|
2952
3288
|
|
|
3289
|
+
// ../packages/twin-stripe/dist/src/apply-seed.js
|
|
3290
|
+
function applySeed(db, seed, failureInjection) {
|
|
3291
|
+
ensureStripeTables(db);
|
|
3292
|
+
for (const entry of seed.api_keys ?? []) {
|
|
3293
|
+
mintApiKey(db, {
|
|
3294
|
+
sid: entry.sid,
|
|
3295
|
+
account_id: entry.account_id,
|
|
3296
|
+
key: entry.key
|
|
3297
|
+
});
|
|
3298
|
+
}
|
|
3299
|
+
for (const row of seed.payment_intents ?? []) {
|
|
3300
|
+
insertSeedPaymentIntent(db, row);
|
|
3301
|
+
}
|
|
3302
|
+
for (const row of seed.charges ?? []) {
|
|
3303
|
+
insertSeedCharge(db, row);
|
|
3304
|
+
}
|
|
3305
|
+
for (const row of seed.balance_transactions ?? []) {
|
|
3306
|
+
insertSeedBalanceTransaction(db, row);
|
|
3307
|
+
}
|
|
3308
|
+
for (const row of seed.refunds ?? []) {
|
|
3309
|
+
insertSeedRefund(db, row);
|
|
3310
|
+
}
|
|
3311
|
+
if (failureInjection) {
|
|
3312
|
+
failureInjection.setRules(seed.failure_injection ?? []);
|
|
3313
|
+
}
|
|
3314
|
+
}
|
|
3315
|
+
function insertSeedPaymentIntent(db, row) {
|
|
3316
|
+
db.prepare(`INSERT INTO payment_intents (
|
|
3317
|
+
id, account_id, amount, currency, status,
|
|
3318
|
+
payment_method_types_json, next_action_json,
|
|
3319
|
+
latest_charge_id, capture_method, confirmation_method,
|
|
3320
|
+
idempotency_key, metadata_json, crypto_deposit_json,
|
|
3321
|
+
client_secret, created, updated, canceled_at, captured_at
|
|
3322
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.id, row.account_id, row.amount, row.currency, row.status, JSON.stringify(row.payment_method_types), row.next_action === void 0 || row.next_action === null ? null : JSON.stringify(row.next_action), row.latest_charge_id ?? null, row.capture_method, row.confirmation_method, row.idempotency_key ?? null, JSON.stringify(row.metadata), row.crypto_deposit === void 0 || row.crypto_deposit === null ? null : JSON.stringify(row.crypto_deposit), row.client_secret, row.created, row.updated, row.canceled_at ?? null, row.captured_at ?? null);
|
|
3323
|
+
}
|
|
3324
|
+
function insertSeedCharge(db, row) {
|
|
3325
|
+
db.prepare(`INSERT INTO charges (
|
|
3326
|
+
id, account_id, payment_intent_id, amount, amount_captured, amount_refunded,
|
|
3327
|
+
status, balance_transaction_id, captured, currency, created
|
|
3328
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.id, row.account_id, row.payment_intent_id, row.amount, row.amount_captured, row.amount_refunded, row.status, row.balance_transaction_id ?? null, row.captured ? 1 : 0, row.currency, row.created);
|
|
3329
|
+
}
|
|
3330
|
+
function insertSeedRefund(db, row) {
|
|
3331
|
+
db.prepare(`INSERT INTO refunds (
|
|
3332
|
+
id, account_id, charge_id, payment_intent_id, amount, currency,
|
|
3333
|
+
status, reason, balance_transaction_id, idempotency_key, created
|
|
3334
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.id, row.account_id, row.charge_id, row.payment_intent_id, row.amount, row.currency, row.status, row.reason ?? null, row.balance_transaction_id ?? null, row.idempotency_key ?? null, row.created);
|
|
3335
|
+
}
|
|
3336
|
+
function insertSeedBalanceTransaction(db, row) {
|
|
3337
|
+
db.prepare(`INSERT INTO balance_transactions (
|
|
3338
|
+
id, account_id, type, amount, fee, net, currency, source_id, source_type,
|
|
3339
|
+
available_on, status, created
|
|
3340
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(row.id, row.account_id, row.type, row.amount, row.fee, row.net, row.currency, row.source_id ?? null, row.source_type ?? null, row.available_on, row.status, row.created);
|
|
3341
|
+
}
|
|
3342
|
+
|
|
2953
3343
|
// ../packages/twin-stripe/dist/src/x402.js
|
|
2954
3344
|
function parsePriceToBaseUnits(price) {
|
|
2955
3345
|
const trimmed = price.trim();
|
|
@@ -4037,4 +4427,4 @@ function createTwinStripeApp(opts = {}) {
|
|
|
4037
4427
|
});
|
|
4038
4428
|
}
|
|
4039
4429
|
|
|
4040
|
-
export { StripeDomain, createStripeTwinDefinition, createTwinStripeApp, executeTool, isMutatingTool, migrate, openTwinStripeDatabase, paymentMiddleware, registerStripeRoutes, registerX402Routes, resetDatabase, stripeToolFixture, stripeToolInputSchema, toolArgumentSchemas, tthwSeconds };
|
|
4430
|
+
export { StripeDomain, applySeed, createStripeTwinDefinition, createTwinStripeApp, executeTool, isMutatingTool, migrate, mintApiKey, openTwinStripeDatabase, paymentMiddleware, registerStripeRoutes, registerX402Routes, resetDatabase, resolveSidFromKey, revokeApiKey, stripeToolFixture, stripeToolInputSchema, toolArgumentSchemas, tthwSeconds };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { GMAIL_CHECKS } from './chunk-JM6VS62R.js';
|
|
2
|
-
import { gmailErrorEnvelope, gmailSeedSchema, parseSeed, defaultSeedState, notFound, invalidArgument, checkFault, unsupported, validateSearchQuery, SEARCH_MAILBOX_MESSAGE_BUDGET, GmailError, parseSearchQuery, CATEGORY_LABELS, parseDate, parseSize, KNOWN_FIELDS, parseDuration, assertHasOperator } from './chunk-
|
|
3
|
-
export { DEFAULT_GMAIL_AGENT_EMAIL, GmailError, SEARCH_MAILBOX_MESSAGE_BUDGET, agentPathInboxMailbox, defaultSeedState, gmailErrorEnvelope, gmailSeedSchema, loadSeedFromEnv, parseSearchQuery, parseSeed, validateSearchQuery } from './chunk-
|
|
2
|
+
import { gmailErrorEnvelope, gmailSeedSchema, parseSeed, defaultSeedState, notFound, invalidArgument, checkFault, unsupported, validateSearchQuery, SEARCH_MAILBOX_MESSAGE_BUDGET, GmailError, parseSearchQuery, CATEGORY_LABELS, parseDate, parseSize, KNOWN_FIELDS, parseDuration, assertHasOperator } from './chunk-PASFBRK4.js';
|
|
3
|
+
export { DEFAULT_GMAIL_AGENT_EMAIL, GmailError, SEARCH_MAILBOX_MESSAGE_BUDGET, agentPathInboxMailbox, defaultSeedState, gmailErrorEnvelope, gmailSeedSchema, loadSeedFromEnv, parseSearchQuery, parseSeed, validateSearchQuery } from './chunk-PASFBRK4.js';
|
|
4
4
|
import './chunk-JWJYNAWI.js';
|
|
5
5
|
import { routeInputDeclarer, integerInput, booleanInput, repeatedInput, mountDeclaredRoute, UndeclaredInputError, MalformedBodyError } from './chunk-IZFM7W2V.js';
|
|
6
|
-
import { loadMcpToolFixture, deriveMcpToolTable, defineTwin, openTwinDatabase, createApp } from './chunk-
|
|
6
|
+
import { loadMcpToolFixture, deriveMcpToolTable, defineTwin, openTwinDatabase, createApp } from './chunk-HRAD7MRX.js';
|
|
7
7
|
import './chunk-6KJC4BTO.js';
|
|
8
8
|
import './chunk-SG6ZTIMT.js';
|
|
9
|
-
import './chunk-
|
|
9
|
+
import './chunk-FBSA5L36.js';
|
|
10
10
|
import { createHash, createHmac, timingSafeEqual, randomBytes } from 'node:crypto';
|
|
11
11
|
import { z } from 'zod';
|
|
12
12
|
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { readSeedFileText, seedForTwin, parseSeedFileText, soleTwinOf, twinsNamedBy } from './chunk-
|
|
2
|
-
import { bootTwin } from './chunk-
|
|
3
|
-
import { TWIN_REGISTRY, isTwinName, TWIN_NAMES, defaultPortFor } from './chunk-
|
|
4
|
-
import './chunk-
|
|
1
|
+
import { readSeedFileText, seedForTwin, parseSeedFileText, soleTwinOf, twinsNamedBy } from './chunk-VPXIGCZW.js';
|
|
2
|
+
import { bootTwin } from './chunk-5NPGY73F.js';
|
|
3
|
+
import { TWIN_REGISTRY, isTwinName, TWIN_NAMES, defaultPortFor } from './chunk-RPPF2KDQ.js';
|
|
4
|
+
import './chunk-HRAD7MRX.js';
|
|
5
5
|
import './chunk-6KJC4BTO.js';
|
|
6
6
|
import './chunk-SG6ZTIMT.js';
|
|
7
|
-
import './chunk-
|
|
7
|
+
import './chunk-FBSA5L36.js';
|
|
8
8
|
import { randomBytes } from 'node:crypto';
|
|
9
9
|
import { readFileSync } from 'node:fs';
|
|
10
10
|
import { mkdir, writeFile } from 'node:fs/promises';
|
package/package.json
CHANGED
|
@@ -65,9 +65,11 @@ account.
|
|
|
65
65
|
### Charge
|
|
66
66
|
|
|
67
67
|
- `ch_test_200` — $200.00 USD (`amount: 20000`), **fully refunded**
|
|
68
|
-
(`amount_refunded: 20000
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
(`amount_refunded: 20000`), `status: succeeded`, `captured: true`. There is no
|
|
69
|
+
remaining refundable balance, so the twin will reject any `create_refund`
|
|
70
|
+
against it with `charge_already_refunded`. The `refunded: true` the agent reads
|
|
71
|
+
back is DERIVED from `amount_refunded >= amount` at serialization, so it is not
|
|
72
|
+
a field the seed writes.
|
|
71
73
|
|
|
72
74
|
## Config
|
|
73
75
|
|