@yiaany/ghostapi 0.1.7 → 0.1.8

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.
Files changed (323) hide show
  1. package/CHANGELOG.md +42 -2
  2. package/CONTRIBUTING.md +119 -117
  3. package/LICENSE +21 -21
  4. package/README.md +208 -185
  5. package/SECURITY.md +53 -37
  6. package/dist/actions/gateway.d.ts +179 -0
  7. package/dist/actions/gateway.js +514 -0
  8. package/dist/actions/gateway.js.map +1 -0
  9. package/dist/actions/index.d.ts +2 -0
  10. package/dist/actions/index.js +2 -0
  11. package/dist/actions/index.js.map +1 -0
  12. package/dist/ai/aiClient.js +4 -4
  13. package/dist/ai/aiClient.js.map +1 -1
  14. package/dist/ai/aiGenerator.d.ts +2 -2
  15. package/dist/ai/aiGenerator.js +21 -72
  16. package/dist/ai/aiGenerator.js.map +1 -1
  17. package/dist/ai/prompts.js +51 -51
  18. package/dist/ai/prompts.js.map +1 -1
  19. package/dist/approvals/approvalInbox.d.ts +150 -0
  20. package/dist/approvals/approvalInbox.js +412 -0
  21. package/dist/approvals/approvalInbox.js.map +1 -0
  22. package/dist/approvals/index.d.ts +2 -0
  23. package/dist/approvals/index.js +2 -0
  24. package/dist/approvals/index.js.map +1 -0
  25. package/dist/behavior/behaviorStore.d.ts +2 -0
  26. package/dist/behavior/behaviorStore.js +50 -46
  27. package/dist/behavior/behaviorStore.js.map +1 -1
  28. package/dist/cache/index.d.ts +2 -0
  29. package/dist/cache/index.js +58 -14
  30. package/dist/cache/index.js.map +1 -1
  31. package/dist/cli/index.js +438 -58
  32. package/dist/cli/index.js.map +1 -1
  33. package/dist/cli/openUrl.d.ts +10 -0
  34. package/dist/cli/openUrl.js +31 -0
  35. package/dist/cli/openUrl.js.map +1 -0
  36. package/dist/cli/parser.d.ts +155 -0
  37. package/dist/cli/parser.js +504 -2
  38. package/dist/cli/parser.js.map +1 -1
  39. package/dist/config/dataPaths.d.ts +31 -0
  40. package/dist/config/dataPaths.js +45 -0
  41. package/dist/config/dataPaths.js.map +1 -0
  42. package/dist/config/localConfig.d.ts +1 -2
  43. package/dist/config/localConfig.js +27 -21
  44. package/dist/config/localConfig.js.map +1 -1
  45. package/dist/config/serverConfig.d.ts +2 -0
  46. package/dist/config/serverConfig.js +8 -1
  47. package/dist/config/serverConfig.js.map +1 -1
  48. package/dist/contracts/contract.d.ts +76 -0
  49. package/dist/contracts/contract.js +603 -0
  50. package/dist/contracts/contract.js.map +1 -0
  51. package/dist/contracts/index.d.ts +2 -0
  52. package/dist/contracts/index.js +2 -0
  53. package/dist/contracts/index.js.map +1 -0
  54. package/dist/credentials/credentialBroker.d.ts +207 -0
  55. package/dist/credentials/credentialBroker.js +588 -0
  56. package/dist/credentials/credentialBroker.js.map +1 -0
  57. package/dist/credentials/index.d.ts +2 -0
  58. package/dist/credentials/index.js +2 -0
  59. package/dist/credentials/index.js.map +1 -0
  60. package/dist/dashboard/app.js +685 -615
  61. package/dist/dashboard/index.html +13 -7
  62. package/dist/dashboard/styles.css +349 -349
  63. package/dist/egress/capabilities.d.ts +32 -0
  64. package/dist/egress/capabilities.js +165 -0
  65. package/dist/egress/capabilities.js.map +1 -0
  66. package/dist/egress/linuxBootstrap.d.ts +1 -0
  67. package/dist/egress/linuxBootstrap.js +121 -0
  68. package/dist/egress/linuxBootstrap.js.map +1 -0
  69. package/dist/egress/run.d.ts +18 -0
  70. package/dist/egress/run.js +305 -0
  71. package/dist/egress/run.js.map +1 -0
  72. package/dist/errors/errorEngine.d.ts +2 -2
  73. package/dist/errors/errorEngine.js +3 -40
  74. package/dist/errors/errorEngine.js.map +1 -1
  75. package/dist/evals/evals.d.ts +126 -0
  76. package/dist/evals/evals.js +466 -0
  77. package/dist/evals/evals.js.map +1 -0
  78. package/dist/evals/index.d.ts +2 -0
  79. package/dist/evals/index.js +2 -0
  80. package/dist/evals/index.js.map +1 -0
  81. package/dist/evidence/index.d.ts +2 -0
  82. package/dist/evidence/index.js +2 -0
  83. package/dist/evidence/index.js.map +1 -0
  84. package/dist/evidence/report.d.ts +143 -0
  85. package/dist/evidence/report.js +556 -0
  86. package/dist/evidence/report.js.map +1 -0
  87. package/dist/fault/faultLab.d.ts +5 -4
  88. package/dist/fault/faultLab.js +66 -24
  89. package/dist/fault/faultLab.js.map +1 -1
  90. package/dist/index.d.ts +46 -0
  91. package/dist/index.js +23 -0
  92. package/dist/index.js.map +1 -1
  93. package/dist/inventory/analysis.d.ts +12 -0
  94. package/dist/inventory/analysis.js +457 -0
  95. package/dist/inventory/analysis.js.map +1 -0
  96. package/dist/inventory/index.d.ts +5 -0
  97. package/dist/inventory/index.js +4 -0
  98. package/dist/inventory/index.js.map +1 -0
  99. package/dist/inventory/inventoryController.d.ts +53 -0
  100. package/dist/inventory/inventoryController.js +1044 -0
  101. package/dist/inventory/inventoryController.js.map +1 -0
  102. package/dist/inventory/types.d.ts +579 -0
  103. package/dist/inventory/types.js +787 -0
  104. package/dist/inventory/types.js.map +1 -0
  105. package/dist/landing/assets/index-CxWsopzP.css +1 -0
  106. package/dist/landing/assets/index-DZlpyhqd.js +55 -0
  107. package/dist/landing/assets/index-Dk-Xezs3.js +55 -0
  108. package/dist/landing/index.html +15 -15
  109. package/dist/ledger/actionLedger.d.ts +125 -0
  110. package/dist/ledger/actionLedger.js +594 -0
  111. package/dist/ledger/actionLedger.js.map +1 -0
  112. package/dist/ledger/index.d.ts +2 -0
  113. package/dist/ledger/index.js +2 -0
  114. package/dist/ledger/index.js.map +1 -0
  115. package/dist/mcp/server.js +4 -3
  116. package/dist/mcp/server.js.map +1 -1
  117. package/dist/policy/index.d.ts +3 -0
  118. package/dist/policy/index.js +2 -0
  119. package/dist/policy/index.js.map +1 -0
  120. package/dist/policy/policy.d.ts +14 -0
  121. package/dist/policy/policy.js +282 -0
  122. package/dist/policy/policy.js.map +1 -0
  123. package/dist/policy/types.d.ts +52 -0
  124. package/dist/policy/types.js +2 -0
  125. package/dist/policy/types.js.map +1 -0
  126. package/dist/productTelemetry/index.d.ts +16 -0
  127. package/dist/productTelemetry/index.js +142 -0
  128. package/dist/productTelemetry/index.js.map +1 -0
  129. package/dist/providers/conformance.d.ts +7 -0
  130. package/dist/providers/conformance.js +48 -0
  131. package/dist/providers/conformance.js.map +1 -0
  132. package/dist/providers/index.d.ts +4 -2
  133. package/dist/providers/index.js +3 -1
  134. package/dist/providers/index.js.map +1 -1
  135. package/dist/providers/packs/resendPack.d.ts +2 -0
  136. package/dist/providers/packs/resendPack.js +147 -0
  137. package/dist/providers/packs/resendPack.js.map +1 -0
  138. package/dist/providers/packs/stripePack.d.ts +2 -0
  139. package/dist/providers/packs/stripePack.js +852 -0
  140. package/dist/providers/packs/stripePack.js.map +1 -0
  141. package/dist/providers/registry.d.ts +7 -3
  142. package/dist/providers/registry.js +55 -4
  143. package/dist/providers/registry.js.map +1 -1
  144. package/dist/providers/resend.js +2 -11
  145. package/dist/providers/resend.js.map +1 -1
  146. package/dist/providers/runtime.d.ts +8 -0
  147. package/dist/providers/runtime.js +48 -0
  148. package/dist/providers/runtime.js.map +1 -0
  149. package/dist/providers/stripeWebhook.d.ts +13 -0
  150. package/dist/providers/stripeWebhook.js +50 -0
  151. package/dist/providers/stripeWebhook.js.map +1 -0
  152. package/dist/providers/types.d.ts +153 -0
  153. package/dist/proxy/cacheKey.js +3 -3
  154. package/dist/proxy/cacheKey.js.map +1 -1
  155. package/dist/proxy/providerDetector.d.ts +2 -7
  156. package/dist/proxy/providerDetector.js +4 -4
  157. package/dist/proxy/providerDetector.js.map +1 -1
  158. package/dist/proxy/proxyHandler.js +116 -12
  159. package/dist/proxy/proxyHandler.js.map +1 -1
  160. package/dist/proxy/requestNormalizer.d.ts +0 -1
  161. package/dist/proxy/requestNormalizer.js +2 -5
  162. package/dist/proxy/requestNormalizer.js.map +1 -1
  163. package/dist/reliability/costGovernance.d.ts +175 -0
  164. package/dist/reliability/costGovernance.js +515 -0
  165. package/dist/reliability/costGovernance.js.map +1 -0
  166. package/dist/reliability/index.d.ts +8 -0
  167. package/dist/reliability/index.js +5 -0
  168. package/dist/reliability/index.js.map +1 -0
  169. package/dist/reliability/reconciliation.d.ts +157 -0
  170. package/dist/reliability/reconciliation.js +522 -0
  171. package/dist/reliability/reconciliation.js.map +1 -0
  172. package/dist/reliability/runtimeHealth.d.ts +60 -0
  173. package/dist/reliability/runtimeHealth.js +356 -0
  174. package/dist/reliability/runtimeHealth.js.map +1 -0
  175. package/dist/reliability/slo.d.ts +131 -0
  176. package/dist/reliability/slo.js +375 -0
  177. package/dist/reliability/slo.js.map +1 -0
  178. package/dist/report/safetyReport.js +7 -3
  179. package/dist/report/safetyReport.js.map +1 -1
  180. package/dist/safety/index.d.ts +2 -0
  181. package/dist/safety/index.js +2 -0
  182. package/dist/safety/index.js.map +1 -0
  183. package/dist/safety/safetyController.d.ts +187 -0
  184. package/dist/safety/safetyController.js +477 -0
  185. package/dist/safety/safetyController.js.map +1 -0
  186. package/dist/scenarios/scenarioBundle.d.ts +75 -0
  187. package/dist/scenarios/scenarioBundle.js +750 -0
  188. package/dist/scenarios/scenarioBundle.js.map +1 -0
  189. package/dist/scenarios/scenarioStore.d.ts +1 -0
  190. package/dist/scenarios/scenarioStore.js +47 -32
  191. package/dist/scenarios/scenarioStore.js.map +1 -1
  192. package/dist/security/headerSanitizer.d.ts +2 -0
  193. package/dist/security/headerSanitizer.js +36 -1
  194. package/dist/security/headerSanitizer.js.map +1 -1
  195. package/dist/security/secrets.js +24 -4
  196. package/dist/security/secrets.js.map +1 -1
  197. package/dist/server/accessControl.d.ts +5 -0
  198. package/dist/server/accessControl.js +100 -0
  199. package/dist/server/accessControl.js.map +1 -0
  200. package/dist/server/createServer.d.ts +0 -5
  201. package/dist/server/createServer.js +9 -29
  202. package/dist/server/createServer.js.map +1 -1
  203. package/dist/server/eventsStore.d.ts +6 -1
  204. package/dist/server/eventsStore.js +83 -15
  205. package/dist/server/eventsStore.js.map +1 -1
  206. package/dist/server/routes.js +36 -10
  207. package/dist/server/routes.js.map +1 -1
  208. package/dist/server/sse.d.ts +2 -1
  209. package/dist/server/sse.js +15 -3
  210. package/dist/server/sse.js.map +1 -1
  211. package/dist/setup/setupGenerator.js +53 -6
  212. package/dist/setup/setupGenerator.js.map +1 -1
  213. package/dist/state/stateStore.d.ts +5 -0
  214. package/dist/state/stateStore.js +48 -62
  215. package/dist/state/stateStore.js.map +1 -1
  216. package/dist/storage/fileStore.d.ts +10 -0
  217. package/dist/storage/fileStore.js +131 -0
  218. package/dist/storage/fileStore.js.map +1 -0
  219. package/dist/teamControl/controlPlane.d.ts +255 -0
  220. package/dist/teamControl/controlPlane.js +918 -0
  221. package/dist/teamControl/controlPlane.js.map +1 -0
  222. package/dist/teamControl/deployment.d.ts +33 -0
  223. package/dist/teamControl/deployment.js +67 -0
  224. package/dist/teamControl/deployment.js.map +1 -0
  225. package/dist/teamControl/index.d.ts +4 -0
  226. package/dist/teamControl/index.js +3 -0
  227. package/dist/teamControl/index.js.map +1 -0
  228. package/dist/tests/testGenerator.js +4 -1
  229. package/dist/tests/testGenerator.js.map +1 -1
  230. package/dist/trust/index.d.ts +2 -0
  231. package/dist/trust/index.js +2 -0
  232. package/dist/trust/index.js.map +1 -0
  233. package/dist/trust/trustLadder.d.ts +182 -0
  234. package/dist/trust/trustLadder.js +560 -0
  235. package/dist/trust/trustLadder.js.map +1 -0
  236. package/dist/worlds/index.d.ts +2 -0
  237. package/dist/worlds/index.js +2 -0
  238. package/dist/worlds/index.js.map +1 -0
  239. package/dist/worlds/worlds.d.ts +160 -0
  240. package/dist/worlds/worlds.js +491 -0
  241. package/dist/worlds/worlds.js.map +1 -0
  242. package/docs/assets/dashboard.png +0 -0
  243. package/docs/ci.md +49 -0
  244. package/docs/commercial/README.md +29 -0
  245. package/docs/commercial/data-inventory.md +36 -0
  246. package/docs/commercial/manual-invoicing.md +44 -0
  247. package/docs/commercial/metrics.md +51 -0
  248. package/docs/commercial/pricing.md +103 -0
  249. package/docs/commercial/privacy-policy-draft.md +41 -0
  250. package/docs/commercial/terms-topics-for-counsel.md +51 -0
  251. package/docs/design-partners/README.md +52 -0
  252. package/docs/design-partners/demo-narratives.md +33 -0
  253. package/docs/design-partners/design-partner-offer.md +39 -0
  254. package/docs/design-partners/discovery-questions.md +28 -0
  255. package/docs/design-partners/feedback-capture-template.md +48 -0
  256. package/docs/design-partners/icp-one-pager.md +43 -0
  257. package/docs/design-partners/onboarding-checklist.md +33 -0
  258. package/docs/design-partners/pilot-success-criteria.md +27 -0
  259. package/docs/design-partners/pricing-interview-script.md +18 -0
  260. package/docs/design-partners/telemetry-plan.md +48 -0
  261. package/docs/development/baseline.md +114 -0
  262. package/docs/development/onboarding-smoke.md +37 -0
  263. package/docs/development/verification-0.1.8.md +25 -0
  264. package/docs/enterprise-product-roadmap-ru.md +1879 -0
  265. package/docs/fundraising/README.md +87 -0
  266. package/docs/fundraising/data-room-checklist.md +72 -0
  267. package/docs/fundraising/demo-script.md +52 -0
  268. package/docs/fundraising/design-partners-50.md +74 -0
  269. package/docs/fundraising/launch-posts.md +37 -0
  270. package/docs/fundraising/metrics-and-evidence.md +30 -0
  271. package/docs/fundraising/roadmap-12-month.md +25 -0
  272. package/docs/fundraising/technical-due-diligence-index.md +37 -0
  273. package/docs/fundraising/yc-application.md +25 -0
  274. package/docs/github-actions.md +84 -0
  275. package/docs/hosted-pilot.md +111 -0
  276. package/docs/mcp.md +52 -50
  277. package/docs/operations/disaster-recovery-runbook.md +81 -0
  278. package/docs/operations/kill-switch-runbook.md +32 -0
  279. package/docs/policy.md +61 -0
  280. package/docs/providers/authoring-packs.md +175 -0
  281. package/docs/providers/stripe-core-pack.md +82 -0
  282. package/docs/release-checklist.md +83 -71
  283. package/docs/release-migration-and-rollback.md +63 -0
  284. package/docs/release-readiness.md +39 -0
  285. package/docs/security/action-gateway-threat-model.md +34 -0
  286. package/docs/security/action-ledger-incident-replay-threat-model.md +42 -0
  287. package/docs/security/approval-inbox-threat-model.md +35 -0
  288. package/docs/security/credential-broker-threat-model.md +52 -0
  289. package/docs/security/egress-threat-model.md +126 -0
  290. package/docs/security/inventory-threat-model.md +104 -0
  291. package/docs/security/kill-switch-budgets-threat-model.md +37 -0
  292. package/docs/security/reliability-threat-model.md +111 -0
  293. package/docs/security/trust-ladder-threat-model.md +33 -0
  294. package/docs/team-control-plane.md +72 -0
  295. package/docs/usage.md +571 -57
  296. package/examples/README.md +10 -0
  297. package/examples/agent-instructions/README.md +39 -39
  298. package/examples/ci-smoke/README.md +21 -0
  299. package/examples/ci-smoke/ghostapi.policy.yaml +22 -0
  300. package/examples/ci-smoke/package.json +9 -0
  301. package/examples/ci-smoke/production-egress.mjs +2 -0
  302. package/examples/ci-smoke/safe.mjs +17 -0
  303. package/examples/evals/README.md +24 -0
  304. package/examples/evals/retry-after.eval.json +52 -0
  305. package/examples/generic-rest/README.md +27 -27
  306. package/examples/github-fetch/README.md +35 -35
  307. package/examples/openai-streaming/README.md +16 -0
  308. package/examples/openai-streaming/streaming-tool-call.mjs +31 -0
  309. package/examples/policy/ghostapi.policy.yaml +27 -0
  310. package/examples/record-replay/README.md +19 -0
  311. package/examples/record-replay/replay-requests.json +22 -0
  312. package/examples/record-replay/stripe-checkout.har.json +30 -0
  313. package/examples/resend-node/README.md +22 -22
  314. package/examples/stripe-node/README.md +35 -29
  315. package/examples/stripe-node/checkout-flow.mjs +61 -0
  316. package/examples/twilio-node/README.md +21 -21
  317. package/examples/worlds/README.md +19 -0
  318. package/examples/worlds/subscription-recovery.mjs +12 -0
  319. package/package.json +27 -12
  320. package/dist/providers/stripe.d.ts +0 -2
  321. package/dist/providers/stripe.js +0 -15
  322. package/dist/providers/stripe.js.map +0 -1
  323. package/docs/assets/ghostapi-avatar.png +0 -0
@@ -0,0 +1,10 @@
1
+ # GhostAPI Starter Examples
2
+
3
+ - `stripe-node/`: Stripe checkout, subscription, refund, and local webhook starter using fake local keys.
4
+ - `openai-streaming/`: OpenAI-shaped streaming/tool-call request against local GhostAPI.
5
+ - `ci-smoke/`: CI policy pass/fail fixtures, including an intentional production-egress failure.
6
+ - `record-replay/`: Sanitized HAR import plus deterministic replay with no live provider traffic.
7
+ - `evals/`: Agent eval spec starter scored from sanitized evidence.
8
+ - `worlds/`: Stateful synthetic world starter for a subscription recovery workflow.
9
+
10
+ Run `npx @yiaany/ghostapi doctor` before using `ghostapi run`; Linux namespace enforcement is not claimed on Windows or macOS.
@@ -1,39 +1,39 @@
1
- # Agent Instructions
2
-
3
- Use these snippets in AI coding tools when you want agents to test external integrations safely through GhostAPI.
4
-
5
- ## Universal Instruction
6
-
7
- ```text
8
- When testing external API integrations, use GhostAPI at http://localhost:8080. Do not send real requests to Stripe, Twilio, Resend, GitHub, Gmail or other external services unless explicitly approved by the user.
9
- ```
10
-
11
- ## Cursor
12
-
13
- ```text
14
- For integration tests and local development, route external API calls through http://localhost:8080. Treat GhostAPI as the only approved target for Stripe, Twilio, Resend, GitHub, Gmail, Slack, Notion, and other external services unless the user explicitly approves live network calls.
15
- ```
16
-
17
- ## Cline
18
-
19
- ```text
20
- Before running code that touches third-party APIs, rewrite base URLs to http://localhost:8080 and use GhostAPI. Never use production API keys or make real external requests without explicit user approval.
21
- ```
22
-
23
- ## Aider
24
-
25
- ```text
26
- When adding or testing API integrations, prefer GhostAPI at http://localhost:8080 for all external services. Keep credentials local and fake. Do not call real Stripe, Twilio, Resend, GitHub, Gmail, or similar APIs unless explicitly instructed.
27
- ```
28
-
29
- ## Codex
30
-
31
- ```text
32
- Use http://localhost:8080 as the base URL for external API integration tests. GhostAPI should simulate provider responses locally. Avoid real network requests to third-party APIs unless explicitly approved by the user.
33
- ```
34
-
35
- ## OpenCode
36
-
37
- ```text
38
- For provider integration work, point SDKs and fetch calls at GhostAPI on http://localhost:8080. Do not send real requests to Stripe, Twilio, Resend, GitHub, Gmail, Slack, Notion, or any other external service without explicit approval.
39
- ```
1
+ # Agent Instructions
2
+
3
+ Use these snippets in AI coding tools when you want agents to test external integrations safely through GhostAPI.
4
+
5
+ ## Universal Instruction
6
+
7
+ ```text
8
+ When testing external API integrations, use GhostAPI at http://localhost:8080. Do not send real requests to Stripe, Twilio, Resend, GitHub, Gmail or other external services unless explicitly approved by the user.
9
+ ```
10
+
11
+ ## Cursor
12
+
13
+ ```text
14
+ For integration tests and local development, route external API calls through http://localhost:8080. Treat GhostAPI as the only approved target for Stripe, Twilio, Resend, GitHub, Gmail, Slack, Notion, and other external services unless the user explicitly approves live network calls.
15
+ ```
16
+
17
+ ## Cline
18
+
19
+ ```text
20
+ Before running code that touches third-party APIs, rewrite base URLs to http://localhost:8080 and use GhostAPI. Never use production API keys or make real external requests without explicit user approval.
21
+ ```
22
+
23
+ ## Aider
24
+
25
+ ```text
26
+ When adding or testing API integrations, prefer GhostAPI at http://localhost:8080 for all external services. Keep credentials local and fake. Do not call real Stripe, Twilio, Resend, GitHub, Gmail, or similar APIs unless explicitly instructed.
27
+ ```
28
+
29
+ ## Codex
30
+
31
+ ```text
32
+ Use http://localhost:8080 as the base URL for external API integration tests. GhostAPI should simulate provider responses locally. Avoid real network requests to third-party APIs unless explicitly approved by the user.
33
+ ```
34
+
35
+ ## OpenCode
36
+
37
+ ```text
38
+ For provider integration work, point SDKs and fetch calls at GhostAPI on http://localhost:8080. Do not send real requests to Stripe, Twilio, Resend, GitHub, Gmail, Slack, Notion, or any other external service without explicit approval.
39
+ ```
@@ -0,0 +1,21 @@
1
+ # GhostAPI CI Smoke Fixture
2
+
3
+ This fixture is used by the repository's GitHub Actions reference workflow and can be run on a Linux host that supports GhostAPI namespaces.
4
+
5
+ ```bash
6
+ export GHOSTAPI_DATA_DIR="$(mktemp -d)"
7
+ ghostapi run --policy ghostapi.policy.yaml -- npm run test:safe
8
+ ```
9
+
10
+ The safe command sends a request only to the GhostAPI endpoint injected by `ghostapi run`. It records `ci.safe_ghostapi`, which the fixture policy requires.
11
+
12
+ The unsafe command is a regression test for the namespace boundary. It must exit non-zero when run through GhostAPI:
13
+
14
+ ```bash
15
+ if ghostapi run --policy ghostapi.policy.yaml -- npm run test:production-egress; then
16
+ echo "unexpected production egress"
17
+ exit 1
18
+ fi
19
+ ```
20
+
21
+ The unsafe fixture must never be run directly on a developer machine or ordinary CI executor because it intentionally targets `api.stripe.com`.
@@ -0,0 +1,22 @@
1
+ version: 1
2
+ network:
3
+ default: deny
4
+ allow:
5
+ - host: localhost
6
+ - host: 127.0.0.1
7
+ deny:
8
+ - host: api.stripe.com
9
+ productionHosts:
10
+ - '*.stripe.com'
11
+ credentials:
12
+ forbid:
13
+ - sk_live_*
14
+ requiredScenarios:
15
+ - ci.safe_ghostapi
16
+ enforcement:
17
+ allowedModes:
18
+ - linux-network-namespace
19
+ reports:
20
+ maxProductionEgressAttempts: 0
21
+ maxForbiddenCredentialMatches: 0
22
+ maxBreakingContractChanges: 0
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "ghostapi-ci-smoke-fixtures",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "test:safe": "node safe.mjs",
7
+ "test:production-egress": "node production-egress.mjs"
8
+ }
9
+ }
@@ -0,0 +1,2 @@
1
+ // This fixture deliberately represents unsafe application behavior. Only run it through ghostapi run.
2
+ await fetch("https://api.stripe.com/v1/customers", { signal: AbortSignal.timeout(5_000) });
@@ -0,0 +1,17 @@
1
+ const baseUrl = process.env.GHOSTAPI_BASE_URL;
2
+
3
+ if (!baseUrl) throw new Error("GHOSTAPI_BASE_URL is required; run this fixture through ghostapi run.");
4
+
5
+ const response = await fetch(`${baseUrl}/v1/customers`, {
6
+ method: "POST",
7
+ headers: {
8
+ "content-type": "application/json"
9
+ },
10
+ body: JSON.stringify({
11
+ email: "ci-safe@example.invalid",
12
+ metadata: { scenario: "ci.safe_ghostapi" }
13
+ })
14
+ });
15
+
16
+ if (!response.ok) throw new Error(`GhostAPI safe fixture failed with HTTP ${response.status}.`);
17
+ console.log("GhostAPI safe fixture completed through the loopback runtime.");
@@ -0,0 +1,24 @@
1
+ # GhostAPI Agent Eval Demo
2
+
3
+ This directory shows the coding-agent workflow for deterministic evals.
4
+
5
+ 1. Run the agent's integration tests through the safety boundary on a supported Linux host:
6
+
7
+ ```bash
8
+ ghostapi run -- npm test
9
+ ```
10
+
11
+ 2. Generate sanitized evidence for the run:
12
+
13
+ ```bash
14
+ ghostapi evidence generate --run .ghostapi/runs/<run-id>/run.json --out .ghostapi/reports/agent.json
15
+ ```
16
+
17
+ 3. Score the evidence with a built-in template or the local JSON spec:
18
+
19
+ ```bash
20
+ ghostapi eval --template retry-after --evidence .ghostapi/reports/agent.json --ci
21
+ ghostapi eval --spec examples/evals/retry-after.eval.json --evidence .ghostapi/reports/agent.json --json
22
+ ```
23
+
24
+ If `--evidence` is omitted, `ghostapi eval --spec ...` launches `task.command` through `ghostapi run`; it never executes the command outside that boundary. Specs that declare `injectedFailures` require pre-generated evidence until the declared synthetic-world setup can be applied automatically. Core score is deterministic and evidence-based. LLM judging is not required and does not affect the security score.
@@ -0,0 +1,52 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "kind": "ghostapi.eval",
4
+ "id": "agent.retry_after",
5
+ "title": "Agent honors Retry-After",
6
+ "syntheticWorld": {
7
+ "world": {
8
+ "id": "subscription-recovery",
9
+ "version": "1.0.0",
10
+ "seed": "demo-seed"
11
+ },
12
+ "providers": ["stripe"],
13
+ "scenarios": ["stripe.rate_limited"]
14
+ },
15
+ "task": {
16
+ "description": "Run the coding-agent integration tests under GhostAPI and verify retry behavior.",
17
+ "command": ["npm", "test"]
18
+ },
19
+ "injectedFailures": [
20
+ {
21
+ "id": "stripe.rate_limited",
22
+ "type": "rate-limit",
23
+ "provider": "stripe",
24
+ "statusCode": 429,
25
+ "retryAfterMs": 2000
26
+ }
27
+ ],
28
+ "expectations": [
29
+ { "id": "retry-observed", "type": "retry-observed", "points": 40 },
30
+ { "id": "no-production-egress", "type": "no-production-egress", "points": 30 },
31
+ { "id": "run-finished", "type": "run-finished", "points": 30 }
32
+ ],
33
+ "forbidden": [
34
+ { "id": "production-egress", "type": "production-egress" },
35
+ { "id": "secret-leak", "type": "secret-leak" }
36
+ ],
37
+ "limits": {
38
+ "timeoutMs": 60000,
39
+ "maxOutputBytes": 524288
40
+ },
41
+ "rubric": {
42
+ "maxScore": 100,
43
+ "components": [
44
+ { "id": "retry-observed", "expectationId": "retry-observed", "points": 40, "reason": "Retry or Retry-After evidence was observed." },
45
+ { "id": "no-production-egress", "expectationId": "no-production-egress", "points": 30, "reason": "Evidence reports zero production egress attempts." },
46
+ { "id": "run-finished", "expectationId": "run-finished", "points": 30, "reason": "The GhostAPI run finished and produced lifecycle evidence." }
47
+ ]
48
+ },
49
+ "judge": {
50
+ "llmAsJudge": false
51
+ }
52
+ }
@@ -1,27 +1,27 @@
1
- # Generic REST Example
2
-
3
- Create a generic task resource through GhostAPI. This path uses the generic fallback, not a native adapter.
4
-
5
- ## Run
6
-
7
- Start GhostAPI:
8
-
9
- ```bash
10
- ghostapi start
11
- ```
12
-
13
- Create a task:
14
-
15
- ```bash
16
- curl -X POST http://localhost:8080/tasks \
17
- -H "content-type: application/json" \
18
- -d '{"title":"Write integration tests","status":"open","priority":"high"}'
19
- ```
20
-
21
- Fetch tasks:
22
-
23
- ```bash
24
- curl http://localhost:8080/tasks
25
- ```
26
-
27
- The generic fallback infers the `task` resource from the path and produces local mock IDs like `task_mock_xxx`.
1
+ # Generic REST Example
2
+
3
+ Create a generic task resource through GhostAPI. This path uses the generic fallback, not a native adapter.
4
+
5
+ ## Run
6
+
7
+ Start GhostAPI:
8
+
9
+ ```bash
10
+ ghostapi start
11
+ ```
12
+
13
+ Create a task:
14
+
15
+ ```bash
16
+ curl -X POST http://localhost:8080/tasks \
17
+ -H "content-type: application/json" \
18
+ -d '{"title":"Write integration tests","status":"open","priority":"high"}'
19
+ ```
20
+
21
+ Fetch tasks:
22
+
23
+ ```bash
24
+ curl http://localhost:8080/tasks
25
+ ```
26
+
27
+ The generic fallback infers the `task` resource from the path and produces local mock IDs like `task_mock_xxx`.
@@ -1,35 +1,35 @@
1
- # GitHub Fetch Example
2
-
3
- Create a GitHub-like issue through GhostAPI using plain `fetch` or `curl`. This does not call GitHub.
4
-
5
- ## Run
6
-
7
- Start GhostAPI:
8
-
9
- ```bash
10
- ghostapi start
11
- ```
12
-
13
- Create an issue:
14
-
15
- ```bash
16
- curl -X POST http://localhost:8080/repos/octo/hello-world/issues \
17
- -H "content-type: application/json" \
18
- -H "x-github-api-version: 2022-11-28" \
19
- -H "authorization: Bearer ghp_local_only" \
20
- -d '{"title":"Local integration test","body":"Created through GhostAPI"}'
21
- ```
22
-
23
- Equivalent JavaScript:
24
-
25
- ```js
26
- await fetch("http://localhost:8080/repos/octo/hello-world/issues", {
27
- method: "POST",
28
- headers: {
29
- "content-type": "application/json",
30
- "x-github-api-version": "2022-11-28",
31
- authorization: "Bearer ghp_local_only"
32
- },
33
- body: JSON.stringify({ title: "Local integration test", body: "Created through GhostAPI" })
34
- });
35
- ```
1
+ # GitHub Fetch Example
2
+
3
+ Create a GitHub-like issue through GhostAPI using plain `fetch` or `curl`. This does not call GitHub.
4
+
5
+ ## Run
6
+
7
+ Start GhostAPI:
8
+
9
+ ```bash
10
+ ghostapi start
11
+ ```
12
+
13
+ Create an issue:
14
+
15
+ ```bash
16
+ curl -X POST http://localhost:8080/repos/octo/hello-world/issues \
17
+ -H "content-type: application/json" \
18
+ -H "x-github-api-version: 2022-11-28" \
19
+ -H "authorization: Bearer ghp_local_only" \
20
+ -d '{"title":"Local integration test","body":"Created through GhostAPI"}'
21
+ ```
22
+
23
+ Equivalent JavaScript:
24
+
25
+ ```js
26
+ await fetch("http://localhost:8080/repos/octo/hello-world/issues", {
27
+ method: "POST",
28
+ headers: {
29
+ "content-type": "application/json",
30
+ "x-github-api-version": "2022-11-28",
31
+ authorization: "Bearer ghp_local_only"
32
+ },
33
+ body: JSON.stringify({ title: "Local integration test", body: "Created through GhostAPI" })
34
+ });
35
+ ```
@@ -0,0 +1,16 @@
1
+ # OpenAI Streaming And Tool Call Starter
2
+
3
+ This starter exercises OpenAI-shaped chat completions against local GhostAPI. It uses a fake key and never requires a live OpenAI account.
4
+
5
+ ```bash
6
+ npx @yiaany/ghostapi start
7
+ node examples/openai-streaming/streaming-tool-call.mjs
8
+ ```
9
+
10
+ When running on a supported Linux host, execute the app through the egress boundary:
11
+
12
+ ```bash
13
+ npx @yiaany/ghostapi run -- node examples/openai-streaming/streaming-tool-call.mjs
14
+ ```
15
+
16
+ Windows and macOS process isolation is unsupported/experimental; use `ghostapi start` and local SDK base URLs there.
@@ -0,0 +1,31 @@
1
+ const baseUrl = process.env.GHOSTAPI_OPENAI_BASE_URL ?? "http://127.0.0.1:8080/v1";
2
+
3
+ const response = await fetch(`${baseUrl}/chat/completions`, {
4
+ method: "POST",
5
+ headers: {
6
+ "content-type": "application/json",
7
+ authorization: `Bearer ${process.env.OPENAI_API_KEY ?? "sk-ghostapi"}`
8
+ },
9
+ body: JSON.stringify({
10
+ model: "gpt-4o-mini",
11
+ stream: true,
12
+ messages: [{ role: "user", content: "Return a local weather tool call for Berlin." }],
13
+ tools: [
14
+ {
15
+ type: "function",
16
+ function: {
17
+ name: "get_weather",
18
+ description: "Return local test weather.",
19
+ parameters: { type: "object", properties: { city: { type: "string" } }, required: ["city"] }
20
+ }
21
+ }
22
+ ]
23
+ })
24
+ });
25
+
26
+ if (!response.ok) throw new Error(`GhostAPI OpenAI request failed: ${response.status} ${await response.text()}`);
27
+
28
+ const text = await response.text();
29
+ if (!text.includes("[DONE]")) throw new Error("Expected a local streaming completion terminator.");
30
+
31
+ console.log("OpenAI streaming/tool-call starter completed against local GhostAPI.");
@@ -0,0 +1,27 @@
1
+ version: 1
2
+ network:
3
+ default: deny
4
+ allow:
5
+ - host: localhost
6
+ - host: 127.0.0.1
7
+ deny:
8
+ - host: api.stripe.com
9
+ - host: api.openai.com
10
+ productionHosts:
11
+ - '*.stripe.com'
12
+ - '*.openai.com'
13
+ credentials:
14
+ forbid:
15
+ - sk_live_*
16
+ - rk_live_*
17
+ - ghp_*
18
+ requiredScenarios:
19
+ - stripe-payment-intent-card-declined
20
+ - stripe-subscription-payment-failed
21
+ enforcement:
22
+ allowedModes:
23
+ - linux-network-namespace
24
+ reports:
25
+ maxProductionEgressAttempts: 0
26
+ maxForbiddenCredentialMatches: 0
27
+ maxBreakingContractChanges: 0
@@ -0,0 +1,19 @@
1
+ # Record/Replay Starter
2
+
3
+ This starter uses a tiny sanitized HAR fixture and a matching request file. It demonstrates the workflow without a live provider key.
4
+
5
+ ```bash
6
+ npx @yiaany/ghostapi record \
7
+ --input examples/record-replay/stripe-checkout.har.json \
8
+ --allow-sandbox-host api.stripe.com \
9
+ --out .ghostapi/scenarios/stripe-checkout.bundle.json \
10
+ --title "Starter checkout" \
11
+ --approve
12
+
13
+ npx @yiaany/ghostapi replay \
14
+ .ghostapi/scenarios/stripe-checkout.bundle.json \
15
+ --requests examples/record-replay/replay-requests.json \
16
+ --json
17
+ ```
18
+
19
+ The fixture uses a fake `sk_test_...` key marker; do not record production traffic.
@@ -0,0 +1,22 @@
1
+ [
2
+ {
3
+ "method": "POST",
4
+ "path": "/v1/checkout/sessions",
5
+ "headers": { "content-type": "application/json" },
6
+ "body": {
7
+ "mode": "payment",
8
+ "success_url": "https://sandbox.example/success",
9
+ "cancel_url": "https://sandbox.example/cancel",
10
+ "line_items": [
11
+ {
12
+ "quantity": 1,
13
+ "price_data": {
14
+ "currency": "usd",
15
+ "unit_amount": 2400,
16
+ "product_data": { "name": "Starter" }
17
+ }
18
+ }
19
+ ]
20
+ }
21
+ }
22
+ ]
@@ -0,0 +1,30 @@
1
+ {
2
+ "log": {
3
+ "version": "1.2",
4
+ "creator": { "name": "ghostapi-starter", "version": "1.0" },
5
+ "entries": [
6
+ {
7
+ "request": {
8
+ "method": "POST",
9
+ "url": "https://api.stripe.com/v1/checkout/sessions",
10
+ "headers": [
11
+ { "name": "authorization", "value": "Bearer sk_test_ghostapi" },
12
+ { "name": "content-type", "value": "application/json" }
13
+ ],
14
+ "postData": {
15
+ "mimeType": "application/json",
16
+ "text": "{\"mode\":\"payment\",\"success_url\":\"https://sandbox.example/success\",\"cancel_url\":\"https://sandbox.example/cancel\",\"line_items\":[{\"quantity\":1,\"price_data\":{\"currency\":\"usd\",\"unit_amount\":2400,\"product_data\":{\"name\":\"Starter\"}}}]}"
17
+ }
18
+ },
19
+ "response": {
20
+ "status": 200,
21
+ "headers": [{ "name": "content-type", "value": "application/json" }],
22
+ "content": {
23
+ "mimeType": "application/json",
24
+ "text": "{\"id\":\"cs_test_starter\",\"object\":\"checkout.session\",\"mode\":\"payment\",\"livemode\":false,\"url\":\"http://127.0.0.1:8080/checkout/cs_test_starter\"}"
25
+ }
26
+ }
27
+ }
28
+ ]
29
+ }
30
+ }
@@ -1,22 +1,22 @@
1
- # Resend Node Example
2
-
3
- Send a Resend-like email through GhostAPI. This does not send a real email.
4
-
5
- ## Run
6
-
7
- Start GhostAPI:
8
-
9
- ```bash
10
- ghostapi start
11
- ```
12
-
13
- Send an email:
14
-
15
- ```bash
16
- curl -X POST http://localhost:8080/emails \
17
- -H "content-type: application/json" \
18
- -H "authorization: Bearer re_local_only" \
19
- -d '{"from":"onboarding@example.com","to":"ada@example.com","subject":"Welcome","html":"<p>Hello from GhostAPI</p>"}'
20
- ```
21
-
22
- GhostAPI detects Resend from `/emails` and returns a local mock email response.
1
+ # Resend Node Example
2
+
3
+ Send a Resend-like email through GhostAPI. This does not send a real email.
4
+
5
+ ## Run
6
+
7
+ Start GhostAPI:
8
+
9
+ ```bash
10
+ ghostapi start
11
+ ```
12
+
13
+ Send an email:
14
+
15
+ ```bash
16
+ curl -X POST http://localhost:8080/emails \
17
+ -H "content-type: application/json" \
18
+ -H "authorization: Bearer re_local_only" \
19
+ -d '{"from":"onboarding@example.com","to":"ada@example.com","subject":"Welcome","html":"<p>Hello from GhostAPI</p>"}'
20
+ ```
21
+
22
+ GhostAPI detects Resend from `/emails` and returns a local mock email response.
@@ -1,29 +1,35 @@
1
- # Stripe Node Example
2
-
3
- Create and fetch a Stripe-like customer through GhostAPI. This does not call Stripe.
4
-
5
- ## Run
6
-
7
- Start GhostAPI:
8
-
9
- ```bash
10
- ghostapi start
11
- ```
12
-
13
- Create a customer:
14
-
15
- ```bash
16
- curl -X POST http://localhost:8080/v1/customers \
17
- -H "content-type: application/json" \
18
- -H "authorization: Bearer stripe_test_local_only" \
19
- -d '{"email":"ada@example.com","name":"Ada Lovelace","metadata":{"source":"ghostapi-example"}}'
20
- ```
21
-
22
- Copy the returned `id`, then fetch it:
23
-
24
- ```bash
25
- curl http://localhost:8080/v1/customers/cus_mock_example \
26
- -H "authorization: Bearer stripe_test_local_only"
27
- ```
28
-
29
- GhostAPI detects Stripe from the `/v1/customers` path and keeps the created object in `.ghostapi/state.json`.
1
+ # Stripe Node Subscription Flow
2
+
3
+ Run the official Stripe Node SDK against GhostAPI without patching SDK source. This example only talks to `127.0.0.1`; it does not call Stripe.
4
+
5
+ ## Run
6
+
7
+ Start GhostAPI:
8
+
9
+ ```bash
10
+ ghostapi start
11
+ ```
12
+
13
+ Install the SDK once in this example directory:
14
+
15
+ ```bash
16
+ npm install stripe
17
+ ```
18
+
19
+ Run the subscription flow:
20
+
21
+ ```bash
22
+ node checkout-flow.mjs
23
+ ```
24
+
25
+ The script creates a customer, product, recurring price, and trial subscription; activates the local renewal control; then verifies the signed `invoice.payment_succeeded` payload with the official Stripe SDK. `delivery_mode=duplicate` deliberately returns the same event again so application-level de-duplication can be tested.
26
+
27
+ The pack accepts SDK-style `application/x-www-form-urlencoded` requests and JSON requests used by direct HTTP clients. It uses Stripe API version `2026-02-25.clover`. Webhook deliveries are pull-based local test endpoints, so this example never asks GhostAPI to send an outbound request.
28
+
29
+ To inspect the generated state:
30
+
31
+ ```bash
32
+ curl http://127.0.0.1:8080/v1/payment_intents?limit=10
33
+ ```
34
+
35
+ See [`docs/providers/stripe-core-pack.md`](../../docs/providers/stripe-core-pack.md) for supported operations and deliberate limits.