@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
@@ -1,71 +1,83 @@
1
- # Release Checklist
2
-
3
- Use this checklist before publishing GhostAPI to GitHub or npm.
4
-
5
- ## Metadata
6
-
7
- - `package.json` has the correct `name`, `version`, `description`, `license`, `bin`, `files`, `keywords`, and repository metadata.
8
- - `README.md` explains value, install, CLI, provider coverage, examples, safety, and contributing.
9
- - `CHANGELOG.md` has an entry for the release.
10
- - `LICENSE`, `SECURITY.md`, `CONTRIBUTING.md`, and `CODE_OF_CONDUCT.md` are present.
11
-
12
- ## Local Verification
13
-
14
- ```bash
15
- npm run typecheck
16
- npm test
17
- npm run build
18
- ```
19
-
20
- Smoke check the built CLI:
21
-
22
- ```bash
23
- node dist/cli/index.js --help
24
- node dist/cli/index.js providers list
25
- node dist/cli/index.js model get
26
- ```
27
-
28
- Run local proxy smoke tests:
29
-
30
- ```bash
31
- node dist/cli/index.js start --offline --port 8080
32
- ```
33
-
34
- Then verify locally:
35
-
36
- ```bash
37
- curl http://localhost:8080/health
38
- curl http://localhost:8080/dashboard
39
- curl -X POST http://localhost:8080/v1/customers -H "content-type: application/json" -d '{"email":"ada@example.com"}'
40
- curl http://localhost:8080/v1/customers
41
- curl -X POST http://localhost:8080/emails -H "content-type: application/json" -d '{"from":"dev@example.com","to":"ada@example.com","subject":"Hello"}'
42
- curl -X POST http://localhost:8080/2010-04-01/Accounts/AC123/Messages.json -H "content-type: application/x-www-form-urlencoded" -d "To=+15551234567&From=+15557654321&Body=Hello"
43
- ```
44
-
45
- ## Package Verification
46
-
47
- ```bash
48
- npm pack --dry-run
49
- ```
50
-
51
- Confirm the package includes only intended release files and does not include:
52
-
53
- - `.ghostapi/`
54
- - `.env`
55
- - `node_modules/`
56
- - local logs
57
- - test output
58
-
59
- ## Safety Checks
60
-
61
- - GhostAPI does not make real provider API calls by default.
62
- - LLM usage requires explicit API key configuration and receives sanitized requests.
63
- - Dashboard events are sanitized.
64
- - Cache keys do not include raw secrets.
65
- - CLI user errors are actionable and do not print confusing stack traces.
66
-
67
- ## Publish
68
-
69
- - Tag the release.
70
- - Push to GitHub.
71
- - Publish to npm only after package dry-run output has been reviewed.
1
+ # Release Checklist
2
+
3
+ Use this checklist before publishing GhostAPI to GitHub or npm.
4
+
5
+ ## Metadata
6
+
7
+ - `package.json` has the correct `name`, `version`, `description`, `license`, `bin`, `files`, `keywords`, and repository metadata.
8
+ - `README.md` explains value, install, CLI, provider coverage, examples, safety, and contributing.
9
+ - `CHANGELOG.md` has an entry for the release.
10
+ - `LICENSE`, `SECURITY.md`, `CONTRIBUTING.md`, and `CODE_OF_CONDUCT.md` are present.
11
+ - [Release readiness matrix](release-readiness.md) and [migration/rollback guide](release-migration-and-rollback.md) are current for the proposed release.
12
+
13
+ ## Local Verification
14
+
15
+ ```bash
16
+ npm run typecheck
17
+ npm test
18
+ npm run build
19
+ npm run smoke:package
20
+ ```
21
+
22
+ Smoke check the built CLI:
23
+
24
+ ```bash
25
+ node dist/cli/index.js --help
26
+ node dist/cli/index.js providers list
27
+ node dist/cli/index.js model get
28
+ ```
29
+
30
+ Run local proxy smoke tests:
31
+
32
+ ```bash
33
+ node dist/cli/index.js start --offline --port 8080
34
+ ```
35
+
36
+ Then verify locally:
37
+
38
+ ```bash
39
+ curl http://localhost:8080/health
40
+ curl http://localhost:8080/dashboard
41
+ curl -X POST http://localhost:8080/v1/customers -H "content-type: application/json" -d '{"email":"ada@example.com"}'
42
+ curl http://localhost:8080/v1/customers
43
+ curl -X POST http://localhost:8080/emails -H "content-type: application/json" -d '{"from":"dev@example.com","to":"ada@example.com","subject":"Hello"}'
44
+ curl -X POST http://localhost:8080/2010-04-01/Accounts/AC123/Messages.json -H "content-type: application/x-www-form-urlencoded" -d "To=+15551234567&From=+15557654321&Body=Hello"
45
+ ```
46
+
47
+ ## Package Verification
48
+
49
+ ```bash
50
+ npm pack --dry-run
51
+ ```
52
+
53
+ Confirm the package includes only intended release files and does not include:
54
+
55
+ - `.ghostapi/`
56
+ - `.env`
57
+ - `node_modules/`
58
+ - local logs
59
+ - test output
60
+
61
+ ## Safety Checks
62
+
63
+ - GhostAPI does not make real provider API calls by default.
64
+ - Ambient `OPENAI_API_KEY` does not enable external LLM access.
65
+ - LLM usage requires explicit opt-in plus `GHOSTAPI_LLM_API_KEY`, and receives sanitized requests.
66
+ - Dashboard events are sanitized.
67
+ - State and persisted event files do not contain secret fixtures used by security tests.
68
+ - Cache keys do not include raw secrets.
69
+ - Ordered request arrays produce distinct cache keys when their order changes.
70
+ - Concurrent child-process state and behavior writes preserve all covered updates.
71
+ - Persisted events rotate at 5 MiB and retain no more than two archives.
72
+ - Non-loopback startup fails without a strong `GHOSTAPI_AUTH_TOKEN`; dashboard APIs and SSE reject missing tokens.
73
+ - Generated tests honor `GHOSTAPI_BASE_URL` instead of requiring port 8080.
74
+ - CLI user errors are actionable and do not print confusing stack traces.
75
+ - GitHub workflows use least-privilege permissions and SHA-pinned actions.
76
+ - Security claims match tests actually run on the target platform; Windows/macOS local simulation is not Linux enforcement evidence.
77
+ - Any full-audit findings have a documented owner and remediation plan.
78
+
79
+ ## Publish
80
+
81
+ - Tag the release.
82
+ - Push to GitHub.
83
+ - Publish to npm only after package dry-run output has been reviewed.
@@ -0,0 +1,63 @@
1
+ # Release Migration And Rollback
2
+
3
+ Last reviewed: 2026-08-08.
4
+
5
+ This guide covers the published local `@yiaany/ghostapi` package. The separate `hosted/` pilot is not part of the npm package and has no production migration or rollback approval.
6
+
7
+ ## Before Upgrade
8
+
9
+ 1. Read the target `CHANGELOG.md`, `SECURITY.md`, platform limitations, and package contents.
10
+ 2. Keep the project policy and scenarios under normal source control only if they contain no sensitive data. `.ghostapi/` can contain local simulation data and evidence; do not upload it as a generic backup.
11
+ 3. If a local backup is needed, make an access-controlled copy of only the required `.ghostapi/` files and review it for secrets before transferring it.
12
+ 4. Run `ghostapi doctor --json`. On Windows and macOS, use `ghostapi start --open` for local simulation; do not expect `ghostapi run` enforcement.
13
+
14
+ ## Upgrade
15
+
16
+ ```bash
17
+ npx @yiaany/ghostapi@<version> init
18
+ npx @yiaany/ghostapi@<version> doctor --json
19
+ ```
20
+
21
+ `init` does not overwrite existing setup files. Review generated setup guidance rather than replacing local policy or agent instructions blindly.
22
+
23
+ For a source checkout, install the pinned lockfile and run:
24
+
25
+ ```bash
26
+ npm ci
27
+ npm run typecheck
28
+ npm test
29
+ npm run build
30
+ npm run smoke:package
31
+ ```
32
+
33
+ On supported Linux runners, also run the selected enforced workflow and generate a sanitized evidence report. A successful Windows/macOS local simulation must not be used as substitute evidence for Linux namespace enforcement.
34
+
35
+ ## Rollback
36
+
37
+ 1. Stop the local GhostAPI process or CI job.
38
+ 2. Reinstall the previously reviewed package version or return the source checkout to the previously reviewed commit using the repository's normal non-destructive deployment procedure.
39
+ 3. Re-run `ghostapi doctor --json` and the same local smoke or CI workflow used before the upgrade.
40
+ 4. Preserve only sanitized evidence needed to explain the rollback. Do not attach raw traffic, secrets, source code, or local data directories to an issue.
41
+ 5. If a local data schema rejects an older runtime, do not hand-edit or delete data in place. Work on an access-controlled copy, report the exact version/error through the security or maintainer channel, and retain the original until a recovery path is reviewed.
42
+
43
+ ## Rollback Scope
44
+
45
+ - The current local runtime has no account, hosted entitlement, billing state, or remote control plane to roll back.
46
+ - `ghostapi telemetry disable` removes the optional local aggregate; it is not a product-version rollback tool.
47
+ - Local file locks coordinate cooperating processes on one filesystem only. Do not attempt a rollback while concurrent GhostAPI processes write the same data directory.
48
+
49
+ ## Release Verification
50
+
51
+ Run these on the proposed release commit:
52
+
53
+ ```bash
54
+ npm ci
55
+ npm run typecheck
56
+ npm test
57
+ npm run build
58
+ npm run smoke:package
59
+ npm pack --dry-run
60
+ npm audit --omit=dev
61
+ ```
62
+
63
+ Also review the package file list, tracked-source secret scan, direct runtime dependency licenses, GitHub workflow permissions/action pins, and the known gaps in [release readiness](release-readiness.md). Both the production-only and full dependency audits must pass for this release.
@@ -0,0 +1,39 @@
1
+ # Release Readiness Matrix
2
+
3
+ Last reviewed: 2026-08-22.
4
+
5
+ This matrix is a release-candidate review, not a publication approval. No Git tag, GitHub release, or npm publication was created during this review.
6
+
7
+ | Feature | Platform / boundary | Guarantee level | Evidence reviewed | Known gap | Owner before release |
8
+ | --- | --- | --- | --- | --- | --- |
9
+ | Local provider simulation, dashboard, MCP | Node.js on Windows and Ubuntu WSL2 | Local simulation only; no real provider calls by default. | Final 0.1.8 root lint and typecheck; 55 files and 341 tests with zero skipped; build; packed-package smoke; full and production audits with zero vulnerabilities. | GitHub Actions has not yet been observed on the exact final pushed commit. | Maintainer: retain the exact-commit CI results before publication. |
10
+ | `ghostapi run` | Linux only when `unshare` and `ip` preflight pass | Loopback-only user/mount/network/PID namespace; fail closed. Not a hostile-code filesystem sandbox. | Native Ubuntu WSL2 enforcement suite passed 12 of 12 tests with zero skipped on 2026-08-22, exercising the Linux namespace boundary. Earlier 0.1.7 WSL evidence remains historical. | Local WSL2 evidence is not a substitute for GitHub Actions on the exact final commit. | Maintainer: observe the pinned workflow after push and retain sanitized evidence. |
11
+ | Policy parser | Local YAML input | Bounded, one-document, no anchors/aliases/interpolation, path-contained parsing. | Unit tests plus 400 deterministic malformed-input cases. | Fuzz corpus is deterministic regression coverage, not a replacement for long-running fuzzing. | Maintainer: extend corpus when syntax support changes. |
12
+ | Evidence reports | Local files and explicit `--run` input | Bounded report/run input, secret redaction, canonical logical hash, fail-closed CI result. | Evidence tests include corruption, traversal, terminal escapes, malformed and oversized run evidence. | Same-user filesystem TOCTOU remains outside the local lock/store threat boundary. | Maintainer: document/assess before any shared filesystem support. |
13
+ | Record/replay and contract import | Local JSON/HAR/OpenAPI input | Bounded JSON only; archives, remote refs, symlinks, unsafe hosts, redirects, and secret-bearing bundles reject. | Scenario and contract suites; deterministic malformed-input coverage. | Sanitization is heuristic and requires operator review before sharing. | Maintainer: maintain provider/sanitizer regression fixtures. |
14
+ | Provider packs | Local runtime | Deterministic provider-shaped behavior; unsupported endpoints fail diagnostically. | Stripe lifecycle/conformance tests and provider tests. | Fidelity remains limited to implemented capabilities, not live-provider parity. | Pack maintainer: add conformance before widening claims. |
15
+ | Root CI workflow | GitHub Actions | Read-only repository token and SHA-pinned actions. | Workflow regression coverage is included in the final root suite; workflow definitions include lint/typecheck/test/build/package/audit, hosted, Docker, and Linux enforcement checks. | The workflows still must be observed on the exact final commit after push. | Maintainer: review and retain the GitHub run before publication. |
16
+ | Hosted pilot | Separate Bun/Elysia codebase, implemented but not deployed | Code-level tenant authorization, role checks, bounded request handling, hashed one-time secrets, durable quotas, idempotency, outbox/worker retries, dead-letter state, retention cleanup, readiness checks, and audit metadata. No live-service guarantee. | Clean hosted install; typecheck; 26 tests with zero skipped, including cloned auth-request body bounds; Bun build; zero-vulnerability audit; local non-root Docker image build; migrations `001`-`004` applied to PostgreSQL 17; concurrent organization quota race passed. | No staging deployment; live Google OAuth, Redis, QStash, sustained load, failover, and disaster-recovery behavior remain unproven. | Hosted owner: complete operational gates before any pilot use. |
17
+ | Product telemetry | Local runtime | Disabled by default, aggregate-only, no network transport; opt-out deletes local aggregate. | Product telemetry tests and package smoke. | Not a hosted/team analytics system. | Product owner: obtain explicit partner need before any networked design. |
18
+
19
+ ## Threat Model Delta Since Session 06
20
+
21
+ - The old proxy-guidance-only model is now explicitly separated from Linux `ghostapi run` enforcement. Unsupported platforms fail closed instead of treating proxy configuration as isolation.
22
+ - Process execution now creates bounded lifecycle evidence, strips secret-shaped target environment values, limits target output, and records only aggregate output-secret/limit signals.
23
+ - Policy, scenario, contract, evidence, replay, and hosted report inputs have bounded parsers and reject traversal, symlink, archive, remote-reference, unsupported-schema, or secret-bearing inputs where applicable.
24
+ - Root CI now explicitly uses `contents: read`; the PR safety workflow remains SHA-pinned, artifact-bounded, and avoids executing fork code in its write-comment job.
25
+ - The hosted pilot now implements bounded request parsing, explicit tenant/role authorization, exact-origin mutation checks, one-time hashed invitation and ingest secrets, durable quotas, worker/outbox retry limits, dead-letter handling, retention cleanup, security headers, and dependency-aware readiness. These are locally tested implementation claims, not evidence of a deployed service.
26
+
27
+ ## Open P2 Items
28
+
29
+ | Item | Plan | Owner |
30
+ | --- | --- | --- |
31
+ | GitHub Actions on the exact final commit is still required before publication. | Push the final commit, observe every required pinned workflow and job, and retain the run plus sanitized evidence links. | Maintainer. |
32
+ | Hosted staging and migration rehearsal are incomplete. | Deploy an isolated staging environment and apply the four application migrations plus the pinned Better Auth migration against production-shaped PostgreSQL; verify rollback/forward-recovery procedures and tenant authorization. | Hosted owner. |
33
+ | Hosted load and queue behavior are unproven. | Exercise production-shaped sustained/burst load, Redis rate limits, QStash signature validation/redelivery, outbox leases, worker retries/dead letters, and backlog drain behavior with measured thresholds. | Hosted owner. |
34
+ | Hosted disaster recovery is unproven. | Run repeated backup/restore and regional dependency-failure drills; record measured RPO/RTO instead of claiming the architectural targets. | Hosted owner. |
35
+ | Live OAuth and operational secret/configuration paths are unproven. | Validate Google OAuth redirect/origin configuration, session expiry/rotation, account-linking restrictions, secret rotation, and failure behavior in staging. | Hosted owner. |
36
+
37
+ ## Release Gate
38
+
39
+ The root local package passed the final local 0.1.8 verification recorded in [the 0.1.8 verification record](development/verification-0.1.8.md). Publication still requires observing GitHub Actions on the exact final commit after push. Do not claim a deployed hosted service, completed hosted operational readiness, Linux enforcement on Windows/macOS, or billing availability from this matrix.
@@ -0,0 +1,34 @@
1
+ # Synthetic Action Gateway Threat Model
2
+
3
+ ## Scope
4
+
5
+ The Session 23 action gateway is a local, data-only implementation of the shared action contract. Its only executor is `ghostapi-synthetic`, which mutates an existing local synthetic world. It has no provider HTTP client, credential input, environment-secret lookup, account configuration, shell execution, webhook delivery, or cloud transport.
6
+
7
+ It is not a production gateway. Real provider accounts, credentials, sandbox accounts, provider calls, external messages, money movement, deployments, and deletes are out of scope until the Session 23 entry gate has documented design-partner requirements, a separate test account, an approved threat model, and explicit owner authorization.
8
+
9
+ ## Trust Boundaries
10
+
11
+ - Agent input: `ActionEnvelope` is untrusted data and is strictly schema-validated.
12
+ - Approval input: `ActionApproval` is structured data bound to the canonical SHA-256 action hash and carries Ed25519 provenance from an injected trusted key. A boolean approval, unsigned JSON, unknown key ID, or invalid signature is not accepted.
13
+ - Policy input: the current local policy is loaded again at submit and execute; its version and SHA-256 source hash must match the approved envelope.
14
+ - Identity input: the execution actor/workload pair must match the approved envelope immediately before side effect.
15
+ - Persistence: action records use a private local directory, per-action lock, atomic replacement, regular-file checks, byte bounds, and receipt-chain validation. This coordinates cooperating local processes only; it is not protection from a malicious same-user actor who can alter both state and runtime.
16
+ - Synthetic adapter: execution delegates only to the existing atomic synthetic-world workflow. It has no ambient network or credential capability.
17
+
18
+ ## Invariants
19
+
20
+ - Canonical serialization sorts object keys and preserves array order. Any argument change changes the action hash and invalidates approval.
21
+ - An approver cannot equal the action actor or workload identity.
22
+ - Approval provenance is verified at submission and re-authenticated from the persisted approval immediately before execution. A missing or unavailable verifier fails closed.
23
+ - Action expiry, approval expiry, policy reference, actor identity, adapter support, and idempotency state are checked immediately before execution.
24
+ - Inbox-issued approvals additionally require verifier-backed durable inbox consumption state; possession of artifact JSON or a trusted public key alone does not authorize gateway execution.
25
+ - Receipts distinguish `requested`, `attempted`, `committed`, `verified`, and `failed`. Each receipt hashes the prior receipt hash plus its canonical content.
26
+ - An `attempted` action is reconciled with `verify` before any subsequent execution. A failed reconciliation is an unknown outcome and is never automatically retried.
27
+ - Duplicate action IDs with a changed envelope or approval are rejected. A verified or committed action returns its existing receipt without another synthetic side effect.
28
+ - Unsupported operations and unsupported compensation fail visibly. The API uses `compensate`, never `rollback`; the current synthetic adapter exposes no compensation.
29
+
30
+ ## Remaining Limits
31
+
32
+ - Policy schema v1 does not yet express action-level authorization. The gateway rechecks the approved policy version/hash to prevent stale-policy execution; a later production policy extension must add an explicit action decision before exposing a non-synthetic adapter.
33
+ - Local receipt chaining is tamper-evident only while the local store and runtime are trusted. It is not an externally immutable ledger or a legal audit record.
34
+ - A future provider adapter must provide provider-specific idempotency proof, safe reconciliation for timeout ambiguity, credentials held behind a broker/gateway boundary, scoped grants, kill-switch/budget checks, durable audit evidence, and explicit compensation semantics before it can execute any real side effect.
@@ -0,0 +1,42 @@
1
+ # Local Action Ledger And Incident Replay Threat Model
2
+
3
+ ## Scope
4
+
5
+ The local action ledger is a typed API for turning an already persisted synthetic action record into a tenant-scoped, append-only timeline. It records hashes and bounded structured facts for intent, identity, policy decision, approval, credential-grant reference, attempts, provider receipt, verification, compensation status, and governance events.
6
+
7
+ It does not add a provider client, provider account, credential vault, HTTP transport, production execution path, production credential, hosted audit service, legal/compliance service, or immutable external storage. The current incident pipeline turns a ledger action into one local deterministic synthetic world plus one data-only scenario bundle. Replay uses the existing in-memory `ScenarioReplayer`; it makes no network request and cannot use original credentials.
8
+
9
+ ## Integrity And Privacy
10
+
11
+ - Each tenant has its own SHA-256 genesis hash and ordered hash chain. Every entry binds its tenant, sequence, timestamp, action reference, stage, structured fields, and previous hash.
12
+ - Tenant metadata stores the current entry count and head hash. Verification detects modified content, reordered entries, removed entries, invalid links, and a mismatched head/count.
13
+ - The store is bounded, strict-schema validated, regular-file/non-symlink checked, serialized with the existing local file lock, and atomically replaced.
14
+ - Ledger values are scalar-only. Raw arguments, payloads, authorization, cookies, tokens, secret/password fields, email, phone, address, card, and body/payload fields are rejected. Action/resource/provider references are persisted only as stable IDs or SHA-256 hashes where the identifier could expose sensitive data.
15
+ - Export verifies the requested tenant chain first and returns entries only for the tenant authorized by the injected access authorizer. It contains no credential material or raw action payload.
16
+
17
+ ## Outcome Semantics
18
+
19
+ - A `verified` ledger stage is emitted only from a gateway `verified` receipt.
20
+ - A failed receipt with `unknown_outcome` becomes `ambiguous` and `requires_reconciliation`; it is never relabeled successful.
21
+ - A committed receipt without a verified receipt remains unverified. The incident fixture reproduces this distinction locally with `409 requires_reconciliation` rather than inventing success.
22
+ - Credential use is a reference only: `grantIdHash`, credential version, or `not_used`. The ledger never receives or exports the underlying secret.
23
+
24
+ ## Retention, Hold, And Deletion
25
+
26
+ - `configureRetention()` records a per-tenant retention policy. `appendEntry` enforces the store bound (`MAX_ENTRIES` 2,000): when the cap is reached, entries older than the tenant's `retentionDays` are rotated out and the tenant's hash chain is relinked to genesis — `previousHash`/`entryHash` are recomputed and `entryCount`/`headHash` updated, so a subsequent `verifyTenant` still passes. Rotation is bounded and never silent at the cap: if the store cannot be brought under `MAX_ENTRIES`, the append is rejected with an explicit retention-review error.
27
+ - Rotation is per-tenant and opt-in: a tenant without a `retentionDays` policy is never rotated (its chain remains strictly append-only), and a tenant under `setLegalHold(true)` is never rotated.
28
+ - `setLegalHold(true)` records an active local hold and blocks `requestDeletion()`.
29
+ - `requestDeletion()` records a request timestamp after the hold check. It does not erase entries, backups, or external copies and does not claim GDPR, SEC, HIPAA, or any other compliance behavior.
30
+ - A real retention/deletion workflow needs an approved retention schedule, backup lifecycle, legal authority, trusted identity, durable external evidence, and a cryptographically preserved anchor before destructive deletion can be designed.
31
+
32
+ ## Claimed Basis And Verification
33
+
34
+ - `policy_decision` and `approval` stages echo caller-supplied decisions as `basis: "caller_claimed"` — they record what the caller asserted at admission time, not an independently verified policy/approval decision, and consumers must treat them as claims.
35
+ - `verifyTenant()` returns `tracked: false` with the tenant's genesis hash as head for a tenant that has no entries, and `tracked: true` for a tenant with entries, so "no ledger yet" is distinguishable from a broken or tampered chain.
36
+
37
+ ## Trust Boundaries And Limits
38
+
39
+ - `LedgerAccessAuthorizer` is injected. The default authorizer denies everything. Test capability helpers are only local test utilities, not authentication or tenant isolation for a deployed service.
40
+ - Tenant isolation applies to calls that go through a correct injected authorizer. A malicious same-user actor who can replace the local state file and runtime is outside this local filesystem model.
41
+ - The chain is tamper-evident, not absolutely immutable. It does not defend against a compromised host, altered application code, deleted backups, an attacker who replaces both data and trusted head/anchor, distributed filesystems, or a dishonest clock.
42
+ - Sanitization is structural and pattern-based. Operators must inspect incident fixtures before sharing them; GhostAPI does not guarantee perfect anonymization.
@@ -0,0 +1,35 @@
1
+ # Local Approval Inbox Threat Model
2
+
3
+ ## Scope
4
+
5
+ The approval inbox is a local typed API for the existing `ghostapi-synthetic` action adapter. It does not enable production providers, credentials, deployments, money movement, email, Slack, webhooks, browser approval links, or external notifications.
6
+
7
+ An approval request is derived from a strict action envelope and its canonical SHA-256 hash. The action's risk is derived by the inbox taxonomy, never accepted from the agent as mutable input. The current synthetic operation maps to `update`; the taxonomy also reserves `read`, `create`, `communicate`, `money_movement`, `delete`, `permission_change`, and `deployment` for future reviewed action contracts.
8
+
9
+ ## Policy And Display
10
+
11
+ An approval policy can restrict environment, actor, resource, amount, confidence, and action velocity. It defines an expiry and escalation timeout. A request exposes its normalized arguments, exact target, expected effects, reversibility, amount availability/value, policy reason, evidence hash, and successful synthetic preflight result. Missing amount evidence fails a policy that sets a maximum amount.
12
+
13
+ ## Approval Invariants
14
+
15
+ - Requests, decisions, artifacts, and audit records are strict schema-v1 local data under `.ghostapi/approvals.json`.
16
+ - Approver identities come from an injected verifier and include a verified stable `principalId`. Unverified caller-shaped objects fail closed.
17
+ - An action actor/workload cannot approve its own action through its approver ID, verified principal ID, or independence key.
18
+ - Critical risks or low confidence require distinct verified principals and `independenceKey` values; aliases cannot satisfy two-person approval.
19
+ - Approval artifacts are action-hash-bound, one-time, expiring, and carry Ed25519 provenance from a durable approval-authority key. They are consumed under the inbox lock before execution starts; resumption never issues or consumes a second artifact.
20
+ - The gateway verifies the signature at submission and again from the persisted record at execution. Inbox artifacts also require verifier-confirmed durable request state with the same request ID, action hash, artifact, and `consumedAt`; the request must be `executing`, or already `executed` with a linked receipt hash. Returning an already completed result additionally requires the inbox's stored receipt hash to match the gateway's durable verified receipt. A gateway configured with only the signing authority's public key cannot execute an inbox artifact.
21
+ - Rejection, revoke, timeout, expiry, policy drift, changed action, or changed execution identity deny execution.
22
+ - Edit-and-resubmit supersedes the prior request and requires a changed canonical action hash.
23
+ - The inbox rechecks the policy at execution and then delegates only to the existing action gateway, which repeats provenance/action/approval/policy/identity/idempotency checks before its synthetic side effect.
24
+ - Every approval transition and verified action receipt are connected through one local SHA-256 audit chain. Local chains are tamper-evident only under the existing filesystem trust model.
25
+
26
+ ## Race And Recovery
27
+
28
+ The inbox serializes approval state and artifact consumption with one private file lock. A revoke that acquires the lock first prevents the side effect; an execution that has consumed the artifact first cannot be revoked as if it were still pending. If the process stops after durable `consumedAt`/`executing` state, recovery resubmits the identical signed artifact and delegates to the gateway's receipt chain. A `requested` receipt continues normally only while the action and approval remain valid; an `attempted` or `committed` receipt can be reconciled after expiry because no new attempt is permitted, and a `verified` receipt is returned without another side effect. The inbox changes to `executed` only after linking that verified receipt hash into its audit chain. Repeated recovery and calls after completion return the same verified receipt. A durable gateway `failed` receipt makes the inbox terminally `execution_failed`; an absent receipt or ambiguous attempted outcome remains `executing` and fail-closed rather than being replayed. Artifact data, local hashes, and filesystem write access are not sufficient to mint new valid approvals without the private signing key. Key rotation is explicit through trusted key IDs; unavailable or unknown verifiers deny recovery and execution.
29
+
30
+ ## Remaining Limits
31
+
32
+ - The inbox is an API, not a hosted UI or notification channel. Slack/email text must never become an approval source of truth.
33
+ - Signing keys are injected; GhostAPI does not generate, escrow, rotate, or recover durable production key material. Operators must keep private keys outside the data directory and distribute only trusted public keys to executors.
34
+ - There is no authentication transport, RBAC service, trusted OIDC integration, external immutable audit sink, real clock authority, policy engine for production action classes, or real provider executor.
35
+ - A future production integration requires an independently deployed identity/approval authority, provider-specific impact schema, policy authorization, credential broker, kill switch, budgets, durable audit evidence, timeout reconciliation, and compensation semantics.
@@ -0,0 +1,52 @@
1
+ # Credential Broker And Workload Identity Threat Model
2
+
3
+ ## Scope
4
+
5
+ The credential broker is a local typed library for a future execution gateway. It does not expose a CLI, MCP tool, HTTP endpoint, environment-variable loader, provider SDK, or credential-return API. The agent/workload never receives upstream secret material through arguments, stdin, environment variables, logs, reports, grants, receipts, or persisted broker metadata.
6
+
7
+ Only server-side execution can read a secret. A caller presents a verified workload identity, a short-lived grant, and an exact action reference. The broker reads secret bytes from an injected vault boundary, passes them directly to an injected server-side executor, then zeroes the temporary byte buffer in a `finally` block. It returns a receipt, never the secret or a bearer token.
8
+
9
+ The included `test-memory-vault`, test executor, workload verifier, action-receipt verifier, and break-glass authorizer exist only for automated tests. They have no network, provider, environment-secret, account, or production side-effect capability. A real integration must supply an existing reviewed vault/KMS adapter and a separately reviewed provider executor; GhostAPI does not implement encryption, key wrapping, or a provider credential protocol.
10
+
11
+ ## Secret Lifecycle
12
+
13
+ 1. Provisioning: an operator registers non-secret metadata: tenant, project, environment, provider, owner workload binding, scope allowlist, expiry, and opaque vault reference. The vault owns secret creation and storage.
14
+ 2. Storage: GhostAPI stores only metadata, grant metadata, and use receipts in `.ghostapi/credential-broker.json`. It rejects unknown fields, symlinks, oversized state, secret-shaped identifiers, and plaintext secret fields. A vault reference is not secret material and must not encode a secret.
15
+ 3. Use: an authenticated workload requests a server-only grant for one exact action ID, action hash, and verified action receipt hash. The broker persists `executing` before vault/provider I/O, then rechecks workload, tenant/project/environment, provider, scopes, credential status, grant status, expiry, and action reference immediately before vault access and through an executor-provided guard immediately before its side effect.
16
+ 4. Rotation: rotation replaces the opaque vault reference, increments the credential version, and revokes every outstanding grant. It does not touch local synthetic worlds, so local simulation stays available.
17
+ 5. Revocation: credential revocation marks the credential and all active grants revoked without waiting for vault/provider I/O. New execution attempts and an executor's final active check are denied before a later side effect.
18
+ 6. Audit: broker state records action-linked grant metadata and bounded execution receipts. It never stores the secret, a raw provider request, or an executor response body.
19
+ 7. Recovery: failures before the provider executor begins receive `failed`; any executor error receives `unknown` because a side effect may already have happened. Neither is retried automatically. Provider-specific reconciliation and duplicate-side-effect handling remain required before a real executor is enabled.
20
+
21
+ ## Workload Identity
22
+
23
+ Schema-v1 workload identities distinguish `agent_run`, `ci_job`, and `production_service`. Each identity binds tenant, project, environment, workload ID, subject ID, run ID, issue time, and expiry. The broker accepts an identity only through an injected verifier; unverified caller-shaped objects fail closed.
24
+
25
+ The identity verifier can additionally report whether an owner workload remains active. `listOrphanedCredentials()` returns non-revoked credentials whose owner workload binding is no longer active, so an operator can revoke or rotate them. It does not automatically broaden, transfer, or delete access.
26
+
27
+ ## Invariants
28
+
29
+ - The grant audience is always `ghostapi-server`; no grant is valid for an agent process.
30
+ - A grant is bounded to one tenant, project, environment, workload kind/ID, provider, sorted scope list, credential version, TTL, and exact action receipt.
31
+ - Standard grants last at most 15 minutes. Break-glass grants require an independent trusted authorizer and last at most 5 minutes.
32
+ - Credential metadata and secret material are separate interfaces. Metadata cannot reconstruct the upstream value.
33
+ - Broker and executor both enforce scope. The executor rejects unsupported scope even if a caller somehow reaches it after broker validation.
34
+ - The executor must call its supplied `assertActive()` immediately before its provider side effect; a future adapter that cannot honor this contract is unsupported.
35
+ - A rotated credential invalidates old grants through both revocation and version mismatch. A revoked or expired grant is rejected even when an old request is replayed.
36
+ - Cross-tenant, project, environment, workload, scope, audience, action, and receipt mismatch all fail closed before secret access.
37
+ - A provider executor must create an action-linked receipt. The current test executor has no real provider capability.
38
+
39
+ ## Break-Glass
40
+
41
+ Break-glass is disabled by default. An implementation must use a trusted human-controlled approval system that validates a short-lived structured approval bound to the exact action ID/hash/receipt. The approver cannot equal the workload subject or workload ID. The broker stores only approval ID, approver ID, and bounded reason in the grant; it does not store an approval token.
42
+
43
+ ## Crash And Memory Limits
44
+
45
+ Node.js does not offer a universal guarantee that secret bytes are absent from every process snapshot, heap copy, debugger, or OS crash dump. The broker minimizes exposure by avoiding strings, logs, environment variables, arguments, persistence, and return values; it uses a temporary `Uint8Array` and clears that buffer after executor completion or failure. Operators must still disable or protect crash/core dumps, debugger attachments, and untrusted process inspection in any real deployment.
46
+
47
+ ## Remaining Limits
48
+
49
+ - This is not a production vault, KMS, HSM, hosted identity provider, approval inbox, provider client, or production action gateway.
50
+ - Local JSON storage is coordination and tamper detection only under the existing single-user filesystem trust model; it is not immutable audit storage.
51
+ - Revocation can stop execution before the executor's final active check, but it cannot undo a provider side effect that already crossed that check; a real provider integration still needs provider idempotency and reconciliation.
52
+ - A real provider executor needs its own test-account gate, provider idempotency/reconciliation proof, action-level policy decision, kill switch, budgets/velocity controls, durable audit sink, timeout ambiguity handling, and compensation semantics before any real side effect is enabled.
@@ -0,0 +1,126 @@
1
+ # Egress Threat Model
2
+
3
+ Last verified: 2026-08-06.
4
+
5
+ ## Security Claim
6
+
7
+ GhostAPI 0.1.x includes a Linux-only `ghostapi run` backend that starts a command in fresh user, mount, network and PID namespaces with loopback only. It provides a fail-closed default-deny network boundary only after local `unshare`/`ip` preflight succeeds. `ghostapi doctor --egress` reports `NO PROCESS LAUNCHED`: it is a capability report, not proof that a specific run was isolated.
8
+
9
+ Changing an SDK base URL, setting `HTTP_PROXY`, or instructing an agent to use GhostAPI is useful **accidental safety**. It is not a hostile-code sandbox and is not evidence that production egress was impossible.
10
+
11
+ No design in this document claims protection from an administrator/root-equivalent actor, a compromised host, or a malicious process with control of the same user account outside a future containment boundary.
12
+
13
+ ## Assets And Security Goals
14
+
15
+ - Prevent accidental calls to production providers while developers and AI agents test code.
16
+ - Make attempted allowed and blocked connections attributable to one `ghostapi run` execution.
17
+ - Prevent direct IP, alternate DNS, UDP/QUIC, local-network and subprocess bypasses when a supported enforcement backend is active.
18
+ - Fail closed when the requested guarantee cannot be established.
19
+ - Avoid persistent, system-wide proxy, DNS, routing, firewall or daemon state.
20
+
21
+ ## Threat Actors
22
+
23
+ | Actor or path | Proxy guidance | Process/container enforcement target |
24
+ | --- | --- | --- |
25
+ | Incorrect application code | Usually caught only when it uses the configured local base URL. | Deny all non-explicit network paths. |
26
+ | AI agent creates another HTTP client | Bypasses guidance. | Same child process remains constrained. |
27
+ | `curl`, shell command, or subprocess | Bypasses guidance. | Descendants must remain in the containment boundary. |
28
+ | Direct IP address | Bypasses hostname-based proxy/DNS policy. | No route/socket path unless explicitly allowed. |
29
+ | Custom DNS resolver or DoH | Bypasses configured resolver assumptions. | Resolver traffic is denied with all other network traffic. |
30
+ | UDP or QUIC | Often bypasses HTTP-only controls. | All socket families and protocols are denied by the boundary. |
31
+ | Local-network target | Often omitted from production-focused allowlists. | Deny by default; allow only deliberate loopback transport. |
32
+ | Malicious same-user process | Out of scope for guidance. | Cannot be contained by a boundary it does not enter; same-user hostile code is not a guarantee from Node permission flags. |
33
+
34
+ ## Guarantee Levels
35
+
36
+ ### HTTP Proxy Guidance
37
+
38
+ GhostAPI configures or documents a local HTTP endpoint and can collect only traffic voluntarily sent there. It can reduce accidental provider calls, but cannot prevent a different HTTP library, an IP literal, custom DNS, subprocess, UDP/QUIC, or local-network request.
39
+
40
+ This is the active guarantee on platforms without the Linux backend and when a Linux preflight fails.
41
+
42
+ ### Process-Level Enforcement
43
+
44
+ A process launcher creates an OS-supported restricted execution boundary and starts the target only after a local preflight passes. The future boundary must cover children and inherited handles, deny all network by default, and expose GhostAPI through an intentionally configured loopback or private transport.
45
+
46
+ On Linux, `ghostapi run -- <command>` now implements a loopback-only process boundary with fresh user, mount, network and PID namespaces. It does not transparently redirect provider TLS traffic and it does not support external network allowlist entries until a reviewed policy gateway exists.
47
+
48
+ ### Container Or Network-Namespace Enforcement
49
+
50
+ The target runs in a separate container or network namespace with only loopback, no host networking, no privileged mode, and no mounted container-control socket. This can provide the strongest planned local guarantee, but still does not protect against the container runtime daemon, an administrator, a compromised host, or an explicitly reintroduced host-network path.
51
+
52
+ This is not implemented in GhostAPI 0.1.x.
53
+
54
+ ### Unsupported Or Degraded
55
+
56
+ If a native primitive is absent, a required privilege is unavailable, or GhostAPI has no reviewed launcher, the command must not claim isolation. It returns a clear degraded or unsupported result and recommends a reviewed container/VM backend where appropriate.
57
+
58
+ ## Platform Capability Model
59
+
60
+ ### Linux
61
+
62
+ Linux network namespaces isolate network devices, IP stacks, routing tables, firewall state, sockets, and related networking resources. The Linux manual also documents that the kernel must be configured with `CONFIG_NET_NS`; namespace lifecycle can naturally clean up devices once the last process exits. [Linux network namespaces](https://man7.org/linux/man-pages/man7/network_namespaces.7.html)
63
+
64
+ Implemented backend: an unprivileged parent performs local preflight, writes sanitized run evidence, and launches the target with fresh user, mount, network and PID namespaces. Only loopback is brought up and GhostAPI starts inside the namespace. The parent never creates a veth, route, firewall rule, proxy rule or global daemon. `--pid --fork --kill-child=SIGTERM` makes bootstrap termination kill the namespace init; when PID 1 exits, the PID namespace cannot retain target descendants. A preflight failure starts no target command.
65
+
66
+ The boundary does not make arbitrary same-user code hostile-safe: a path-based UNIX socket already accessible to the same user, such as a Docker/Podman control socket, is not an IP route and can act as a privileged deputy. The backend does not mount a control socket itself, but it also does not yet construct a filesystem sandbox that hides every host socket.
67
+
68
+ ### Containers
69
+
70
+ Docker documents `--network none` as a mode that creates only a loopback interface inside the container. [Docker none network driver](https://docs.docker.com/engine/network/drivers/none/)
71
+
72
+ Planned backend: use an OCI runtime only when a bounded image/mount policy is available. `--network host`, privileged containers, mounted Docker/Podman sockets, and host credentials invalidate the intended boundary. GhostAPI will not start or configure a privileged daemon.
73
+
74
+ ### Windows
75
+
76
+ Microsoft documents AppContainer as an isolation environment with network access granted only for explicitly allocated Internet, intranet, or server capabilities. [AppContainer isolation](https://learn.microsoft.com/en-us/windows/win32/secauthz/appcontainer-isolation)
77
+
78
+ Planned backend: a per-run AppContainer or LPAC launcher with no network capabilities and a dedicated writable directory. GhostAPI does not create profiles or launch AppContainers today, and a normal Win32 child process is not constrained. A future implementation must clean up its profile deterministically without changing global Windows Firewall state.
79
+
80
+ ### macOS
81
+
82
+ Apple's App Sandbox is entitlement-based and intended for signed application bundles, not a general-purpose wrapper for arbitrary developer shell commands. [App Sandbox](https://developer.apple.com/documentation/security/app-sandbox)
83
+
84
+ Planned backend: use an explicit container or VM backend before claiming egress enforcement for arbitrary child commands. GhostAPI must not report `isolated` solely because proxy environment variables or a deprecated sandbox wrapper exists.
85
+
86
+ ### Node.js Runtime
87
+
88
+ Node's Permission Model is activated with `--permission`; a launched Node process without `--allow-net` is denied network access. Node explicitly describes the model as a seat belt for trusted code and says it does not provide security guarantees against malicious code. [Node.js Permissions](https://nodejs.org/api/permissions.html)
89
+
90
+ GhostAPI reports this as a degraded auxiliary control only. It cannot contain non-Node children, is not the future `ghostapi run` hostile-sandbox boundary, and does not replace OS-level isolation.
91
+
92
+ ## Capability API And CLI Contract
93
+
94
+ ```bash
95
+ ghostapi doctor --egress
96
+ ghostapi doctor --egress --json
97
+ ```
98
+
99
+ The JSON report is offline and deterministic apart from local runtime facts. It contains:
100
+
101
+ - `schemaVersion` for machine consumers.
102
+ - `isolated`, which is currently always `false`.
103
+ - `currentGuarantee`, currently `http-proxy-guidance`.
104
+ - Platform/runtime facts and one record per possible backend.
105
+ - Backend status: `available`, `degraded`, `not-implemented`, or `unsupported`.
106
+ - Required privileges/setup and remaining bypasses.
107
+ - A `globalStateChanged: false` invariant.
108
+
109
+ The diagnostic command does not open a network connection, change proxy settings, add firewall rules, create network namespaces, create an AppContainer profile, or contact a container daemon. `ghostapi run` performs the Linux namespace preflight and creates only child-owned namespaces.
110
+
111
+ ## Minimal Cross-Platform Architecture
112
+
113
+ 1. A platform-neutral policy compiler canonicalizes the allow/deny policy, local GhostAPI transport, command arguments, and run ID.
114
+ 2. An unprivileged parent creates evidence and validates the selected backend before spawning the target.
115
+ 3. The Linux backend implements `prepare`, `spawn`, lifecycle evidence and namespace cleanup; Windows AppContainer/LPAC and an explicit OCI/VM runner remain future reviewed backends.
116
+ 4. Each backend owns its resources by process or container lifetime. Crash cleanup relies on resource ownership, with bounded reconciliation only for leftovers that can be safely identified by a run-specific marker.
117
+ 5. A per-run recorder emits attempted connection metadata and a signed/finalized local evidence artifact. It must distinguish a setup failure from a blocked request and an unknown outcome.
118
+ 6. A backend that cannot prove the requested guarantee returns `unsupported` or `degraded`; it never silently falls back to proxy guidance for a command advertised as isolated.
119
+
120
+ ## Non-Goals For The First `ghostapi run`
121
+
122
+ - Global firewall, global proxy, global DNS, hosts-file, routing-table, or system service changes.
123
+ - Transparent interception of another user's process.
124
+ - Protection from root/administrator, the host kernel, or a compromised container runtime.
125
+ - Hidden installation of a privileged daemon.
126
+ - A claim that Node permissions sandbox hostile code.