@polardbx/pxbaas 0.0.0-stage → 0.1.0-beta.10

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 (312) hide show
  1. package/README.md +223 -2
  2. package/bin/pxbaas.js +13 -0
  3. package/dist/app/local-index.d.ts +70 -0
  4. package/dist/app/local-index.d.ts.map +1 -0
  5. package/dist/app/local-index.js +140 -0
  6. package/dist/app/local-index.js.map +1 -0
  7. package/dist/app/preflight.d.ts +61 -0
  8. package/dist/app/preflight.d.ts.map +1 -0
  9. package/dist/app/preflight.js +115 -0
  10. package/dist/app/preflight.js.map +1 -0
  11. package/dist/app/spec-lint.d.ts +45 -0
  12. package/dist/app/spec-lint.d.ts.map +1 -0
  13. package/dist/app/spec-lint.js +423 -0
  14. package/dist/app/spec-lint.js.map +1 -0
  15. package/dist/app/templates.d.ts +167 -0
  16. package/dist/app/templates.d.ts.map +1 -0
  17. package/dist/app/templates.js +151 -0
  18. package/dist/app/templates.js.map +1 -0
  19. package/dist/cli/help-guides.d.ts +17 -0
  20. package/dist/cli/help-guides.d.ts.map +1 -0
  21. package/dist/cli/help-guides.js +132 -0
  22. package/dist/cli/help-guides.js.map +1 -0
  23. package/dist/cli/root.d.ts +3 -0
  24. package/dist/cli/root.d.ts.map +1 -0
  25. package/dist/cli/root.js +75 -0
  26. package/dist/cli/root.js.map +1 -0
  27. package/dist/commands/app/index.d.ts +8 -0
  28. package/dist/commands/app/index.d.ts.map +1 -0
  29. package/dist/commands/app/index.js +1907 -0
  30. package/dist/commands/app/index.js.map +1 -0
  31. package/dist/commands/auth/index.d.ts +3 -0
  32. package/dist/commands/auth/index.d.ts.map +1 -0
  33. package/dist/commands/auth/index.js +198 -0
  34. package/dist/commands/auth/index.js.map +1 -0
  35. package/dist/commands/completion/index.d.ts +3 -0
  36. package/dist/commands/completion/index.d.ts.map +1 -0
  37. package/dist/commands/completion/index.js +14 -0
  38. package/dist/commands/completion/index.js.map +1 -0
  39. package/dist/commands/data/index.d.ts +55 -0
  40. package/dist/commands/data/index.d.ts.map +1 -0
  41. package/dist/commands/data/index.js +407 -0
  42. package/dist/commands/data/index.js.map +1 -0
  43. package/dist/commands/db/index.d.ts +29 -0
  44. package/dist/commands/db/index.d.ts.map +1 -0
  45. package/dist/commands/db/index.js +500 -0
  46. package/dist/commands/db/index.js.map +1 -0
  47. package/dist/commands/doctor/index.d.ts +3 -0
  48. package/dist/commands/doctor/index.d.ts.map +1 -0
  49. package/dist/commands/doctor/index.js +305 -0
  50. package/dist/commands/doctor/index.js.map +1 -0
  51. package/dist/commands/functions/delete.d.ts +3 -0
  52. package/dist/commands/functions/delete.d.ts.map +1 -0
  53. package/dist/commands/functions/delete.js +55 -0
  54. package/dist/commands/functions/delete.js.map +1 -0
  55. package/dist/commands/functions/deploy.d.ts +3 -0
  56. package/dist/commands/functions/deploy.d.ts.map +1 -0
  57. package/dist/commands/functions/deploy.js +118 -0
  58. package/dist/commands/functions/deploy.js.map +1 -0
  59. package/dist/commands/functions/index.d.ts +3 -0
  60. package/dist/commands/functions/index.d.ts.map +1 -0
  61. package/dist/commands/functions/index.js +15 -0
  62. package/dist/commands/functions/index.js.map +1 -0
  63. package/dist/commands/functions/list.d.ts +6 -0
  64. package/dist/commands/functions/list.d.ts.map +1 -0
  65. package/dist/commands/functions/list.js +63 -0
  66. package/dist/commands/functions/list.js.map +1 -0
  67. package/dist/commands/functions/new.d.ts +7 -0
  68. package/dist/commands/functions/new.d.ts.map +1 -0
  69. package/dist/commands/functions/new.js +72 -0
  70. package/dist/commands/functions/new.js.map +1 -0
  71. package/dist/commands/gen/index.d.ts +3 -0
  72. package/dist/commands/gen/index.d.ts.map +1 -0
  73. package/dist/commands/gen/index.js +323 -0
  74. package/dist/commands/gen/index.js.map +1 -0
  75. package/dist/commands/guide/index.d.ts +8 -0
  76. package/dist/commands/guide/index.d.ts.map +1 -0
  77. package/dist/commands/guide/index.js +20 -0
  78. package/dist/commands/guide/index.js.map +1 -0
  79. package/dist/commands/instance/index.d.ts +8 -0
  80. package/dist/commands/instance/index.d.ts.map +1 -0
  81. package/dist/commands/instance/index.js +481 -0
  82. package/dist/commands/instance/index.js.map +1 -0
  83. package/dist/commands/login/index.d.ts +3 -0
  84. package/dist/commands/login/index.d.ts.map +1 -0
  85. package/dist/commands/login/index.js +145 -0
  86. package/dist/commands/login/index.js.map +1 -0
  87. package/dist/commands/logout/index.d.ts +3 -0
  88. package/dist/commands/logout/index.d.ts.map +1 -0
  89. package/dist/commands/logout/index.js +41 -0
  90. package/dist/commands/logout/index.js.map +1 -0
  91. package/dist/commands/profile/import-env.d.ts +18 -0
  92. package/dist/commands/profile/import-env.d.ts.map +1 -0
  93. package/dist/commands/profile/import-env.js +206 -0
  94. package/dist/commands/profile/import-env.js.map +1 -0
  95. package/dist/commands/profile/index.d.ts +3 -0
  96. package/dist/commands/profile/index.d.ts.map +1 -0
  97. package/dist/commands/profile/index.js +124 -0
  98. package/dist/commands/profile/index.js.map +1 -0
  99. package/dist/commands/rest/index.d.ts +3 -0
  100. package/dist/commands/rest/index.d.ts.map +1 -0
  101. package/dist/commands/rest/index.js +102 -0
  102. package/dist/commands/rest/index.js.map +1 -0
  103. package/dist/commands/skill/index.d.ts +11 -0
  104. package/dist/commands/skill/index.d.ts.map +1 -0
  105. package/dist/commands/skill/index.js +228 -0
  106. package/dist/commands/skill/index.js.map +1 -0
  107. package/dist/commands/status/index.d.ts +3 -0
  108. package/dist/commands/status/index.d.ts.map +1 -0
  109. package/dist/commands/status/index.js +59 -0
  110. package/dist/commands/status/index.js.map +1 -0
  111. package/dist/commands/storage/index.d.ts +3 -0
  112. package/dist/commands/storage/index.d.ts.map +1 -0
  113. package/dist/commands/storage/index.js +400 -0
  114. package/dist/commands/storage/index.js.map +1 -0
  115. package/dist/commands/tenant/index.d.ts +19 -0
  116. package/dist/commands/tenant/index.d.ts.map +1 -0
  117. package/dist/commands/tenant/index.js +667 -0
  118. package/dist/commands/tenant/index.js.map +1 -0
  119. package/dist/commands/whoami/index.d.ts +3 -0
  120. package/dist/commands/whoami/index.d.ts.map +1 -0
  121. package/dist/commands/whoami/index.js +101 -0
  122. package/dist/commands/whoami/index.js.map +1 -0
  123. package/dist/credentials/commit.d.ts +38 -0
  124. package/dist/credentials/commit.d.ts.map +1 -0
  125. package/dist/credentials/commit.js +57 -0
  126. package/dist/credentials/commit.js.map +1 -0
  127. package/dist/credentials/credential-store.d.ts +86 -0
  128. package/dist/credentials/credential-store.d.ts.map +1 -0
  129. package/dist/credentials/credential-store.js +282 -0
  130. package/dist/credentials/credential-store.js.map +1 -0
  131. package/dist/credentials/env-file.d.ts +85 -0
  132. package/dist/credentials/env-file.d.ts.map +1 -0
  133. package/dist/credentials/env-file.js +193 -0
  134. package/dist/credentials/env-file.js.map +1 -0
  135. package/dist/credentials/formatter.d.ts +39 -0
  136. package/dist/credentials/formatter.d.ts.map +1 -0
  137. package/dist/credentials/formatter.js +79 -0
  138. package/dist/credentials/formatter.js.map +1 -0
  139. package/dist/credentials/index.d.ts +13 -0
  140. package/dist/credentials/index.d.ts.map +1 -0
  141. package/dist/credentials/index.js +13 -0
  142. package/dist/credentials/index.js.map +1 -0
  143. package/dist/credentials/jwt-introspect.d.ts +39 -0
  144. package/dist/credentials/jwt-introspect.d.ts.map +1 -0
  145. package/dist/credentials/jwt-introspect.js +64 -0
  146. package/dist/credentials/jwt-introspect.js.map +1 -0
  147. package/dist/credentials/masker.d.ts +23 -0
  148. package/dist/credentials/masker.d.ts.map +1 -0
  149. package/dist/credentials/masker.js +40 -0
  150. package/dist/credentials/masker.js.map +1 -0
  151. package/dist/credentials/profile.d.ts +95 -0
  152. package/dist/credentials/profile.d.ts.map +1 -0
  153. package/dist/credentials/profile.js +207 -0
  154. package/dist/credentials/profile.js.map +1 -0
  155. package/dist/credentials/tenant-guard.d.ts +16 -0
  156. package/dist/credentials/tenant-guard.d.ts.map +1 -0
  157. package/dist/credentials/tenant-guard.js +53 -0
  158. package/dist/credentials/tenant-guard.js.map +1 -0
  159. package/dist/credentials/tty-guard.d.ts +29 -0
  160. package/dist/credentials/tty-guard.d.ts.map +1 -0
  161. package/dist/credentials/tty-guard.js +79 -0
  162. package/dist/credentials/tty-guard.js.map +1 -0
  163. package/dist/db/apply-schema.d.ts +144 -0
  164. package/dist/db/apply-schema.d.ts.map +1 -0
  165. package/dist/db/apply-schema.js +359 -0
  166. package/dist/db/apply-schema.js.map +1 -0
  167. package/dist/db/introspect.d.ts +54 -0
  168. package/dist/db/introspect.d.ts.map +1 -0
  169. package/dist/db/introspect.js +140 -0
  170. package/dist/db/introspect.js.map +1 -0
  171. package/dist/db/sql-file.d.ts +104 -0
  172. package/dist/db/sql-file.d.ts.map +1 -0
  173. package/dist/db/sql-file.js +584 -0
  174. package/dist/db/sql-file.js.map +1 -0
  175. package/dist/instance/provision.d.ts +89 -0
  176. package/dist/instance/provision.d.ts.map +1 -0
  177. package/dist/instance/provision.js +139 -0
  178. package/dist/instance/provision.js.map +1 -0
  179. package/dist/instance/zero-store.d.ts +47 -0
  180. package/dist/instance/zero-store.d.ts.map +1 -0
  181. package/dist/instance/zero-store.js +91 -0
  182. package/dist/instance/zero-store.js.map +1 -0
  183. package/dist/instance/zero-whitelist.d.ts +39 -0
  184. package/dist/instance/zero-whitelist.d.ts.map +1 -0
  185. package/dist/instance/zero-whitelist.js +67 -0
  186. package/dist/instance/zero-whitelist.js.map +1 -0
  187. package/dist/main.d.ts +3 -0
  188. package/dist/main.d.ts.map +1 -0
  189. package/dist/main.js +69 -0
  190. package/dist/main.js.map +1 -0
  191. package/dist/skill/agents-md.d.ts +25 -0
  192. package/dist/skill/agents-md.d.ts.map +1 -0
  193. package/dist/skill/agents-md.js +62 -0
  194. package/dist/skill/agents-md.js.map +1 -0
  195. package/dist/skill/assets.d.ts +38 -0
  196. package/dist/skill/assets.d.ts.map +1 -0
  197. package/dist/skill/assets.js +111 -0
  198. package/dist/skill/assets.js.map +1 -0
  199. package/dist/skill/hint.d.ts +39 -0
  200. package/dist/skill/hint.d.ts.map +1 -0
  201. package/dist/skill/hint.js +109 -0
  202. package/dist/skill/hint.js.map +1 -0
  203. package/dist/skill/hosts.d.ts +45 -0
  204. package/dist/skill/hosts.d.ts.map +1 -0
  205. package/dist/skill/hosts.js +96 -0
  206. package/dist/skill/hosts.js.map +1 -0
  207. package/dist/skill/installer.d.ts +100 -0
  208. package/dist/skill/installer.d.ts.map +1 -0
  209. package/dist/skill/installer.js +241 -0
  210. package/dist/skill/installer.js.map +1 -0
  211. package/dist/skill/ownership.d.ts +35 -0
  212. package/dist/skill/ownership.d.ts.map +1 -0
  213. package/dist/skill/ownership.js +52 -0
  214. package/dist/skill/ownership.js.map +1 -0
  215. package/dist/tenant/bundle.d.ts +66 -0
  216. package/dist/tenant/bundle.d.ts.map +1 -0
  217. package/dist/tenant/bundle.js +132 -0
  218. package/dist/tenant/bundle.js.map +1 -0
  219. package/dist/tenant/guide.d.ts +50 -0
  220. package/dist/tenant/guide.d.ts.map +1 -0
  221. package/dist/tenant/guide.js +152 -0
  222. package/dist/tenant/guide.js.map +1 -0
  223. package/dist/tenant/probe.d.ts +65 -0
  224. package/dist/tenant/probe.d.ts.map +1 -0
  225. package/dist/tenant/probe.js +159 -0
  226. package/dist/tenant/probe.js.map +1 -0
  227. package/dist/tenant/verify.d.ts +37 -0
  228. package/dist/tenant/verify.d.ts.map +1 -0
  229. package/dist/tenant/verify.js +132 -0
  230. package/dist/tenant/verify.js.map +1 -0
  231. package/dist/version.d.ts +29 -0
  232. package/dist/version.d.ts.map +1 -0
  233. package/dist/version.js +65 -0
  234. package/dist/version.js.map +1 -0
  235. package/package.json +63 -3
  236. package/skills/pxbaas-app-spec/SKILL.md +165 -0
  237. package/skills/pxbaas-app-spec/references/deploy-options.md +158 -0
  238. package/skills/pxbaas-app-spec/references/guardrails-pitfalls.md +89 -0
  239. package/skills/pxbaas-app-spec/references/runtime-contract.md +151 -0
  240. package/skills/pxbaas-app-spec/references/ssr-session.md +121 -0
  241. package/skills/pxbaas-app-spec/references/templates-examples.md +311 -0
  242. package/skills/pxbaas-cli/SKILL.md +186 -0
  243. package/skills/pxbaas-cli/references/api-reference.md +68 -0
  244. package/skills/pxbaas-cli/references/app-deploy.md +186 -0
  245. package/skills/pxbaas-cli/references/auth-and-credentials.md +116 -0
  246. package/skills/pxbaas-cli/references/data-postgrest.md +101 -0
  247. package/skills/pxbaas-cli/references/db-and-meta.md +102 -0
  248. package/skills/pxbaas-cli/references/edge-functions.md +71 -0
  249. package/skills/pxbaas-cli/references/multi-tenant-apps.md +138 -0
  250. package/skills/pxbaas-cli/references/provision.md +101 -0
  251. package/skills/pxbaas-cli/references/safety-and-two-phase.md +78 -0
  252. package/skills/pxbaas-cli/references/storage.md +61 -0
  253. package/skills/pxbaas-cli/references/tenant-admin.md +122 -0
  254. package/skills/pxbaas-cli/references/troubleshooting.md +76 -0
  255. package/templates/webapp/api/index.ts +55 -0
  256. package/templates/webapp/csr-bff/README.md +81 -0
  257. package/templates/webapp/csr-bff/backend/index.ts +168 -0
  258. package/templates/webapp/csr-bff/db/rls.json +13 -0
  259. package/templates/webapp/csr-bff/db/schema.sql +49 -0
  260. package/templates/webapp/csr-bff/frontend/dist/admin.html +101 -0
  261. package/templates/webapp/csr-bff/frontend/dist/article.html +44 -0
  262. package/templates/webapp/csr-bff/frontend/dist/blog.js +206 -0
  263. package/templates/webapp/csr-bff/frontend/dist/blogger.html +53 -0
  264. package/templates/webapp/csr-bff/frontend/dist/index.html +70 -0
  265. package/templates/webapp/csr-bff/frontend/dist/login.html +56 -0
  266. package/templates/webapp/csr-bff/frontend/dist/profile.html +59 -0
  267. package/templates/webapp/csr-bff/frontend/dist/signup.html +78 -0
  268. package/templates/webapp/csr-bff/frontend/dist/style.css +27 -0
  269. package/templates/webapp/manifest.json +419 -0
  270. package/templates/webapp/mpa/about.html +29 -0
  271. package/templates/webapp/mpa/app.js +42 -0
  272. package/templates/webapp/mpa/index.html +42 -0
  273. package/templates/webapp/mpa/index.ts +60 -0
  274. package/templates/webapp/mpa/style.css +42 -0
  275. package/templates/webapp/react-vite/frontend/index.html +12 -0
  276. package/templates/webapp/react-vite/frontend/package-lock.json +1826 -0
  277. package/templates/webapp/react-vite/frontend/package.json +23 -0
  278. package/templates/webapp/react-vite/frontend/src/App.tsx +34 -0
  279. package/templates/webapp/react-vite/frontend/src/main.tsx +13 -0
  280. package/templates/webapp/react-vite/frontend/src/style.css +46 -0
  281. package/templates/webapp/react-vite/frontend/tsconfig.json +20 -0
  282. package/templates/webapp/react-vite/frontend/vite.config.ts +10 -0
  283. package/templates/webapp/react-vite-hono/backend/index.ts +38 -0
  284. package/templates/webapp/react-vite-hono/frontend/index.html +12 -0
  285. package/templates/webapp/react-vite-hono/frontend/package-lock.json +1826 -0
  286. package/templates/webapp/react-vite-hono/frontend/package.json +23 -0
  287. package/templates/webapp/react-vite-hono/frontend/src/App.tsx +47 -0
  288. package/templates/webapp/react-vite-hono/frontend/src/main.tsx +13 -0
  289. package/templates/webapp/react-vite-hono/frontend/src/style.css +66 -0
  290. package/templates/webapp/react-vite-hono/frontend/tsconfig.json +20 -0
  291. package/templates/webapp/react-vite-hono/frontend/vite.config.ts +10 -0
  292. package/templates/webapp/spa/index.ts +119 -0
  293. package/templates/webapp/ssr-auth/backend/index.ts +133 -0
  294. package/templates/webapp/ssr-auth/frontend/dist/index.html +15 -0
  295. package/templates/webapp/ssr-blog/README.md +111 -0
  296. package/templates/webapp/ssr-blog/backend/index.ts +764 -0
  297. package/templates/webapp/ssr-blog/db/rls.json +13 -0
  298. package/templates/webapp/ssr-blog/db/schema.sql +51 -0
  299. package/templates/webapp/ssr-blog/frontend/dist/index.html +39 -0
  300. package/templates/webapp/ssr-frameworks/README.md +64 -0
  301. package/templates/webapp/ssr-frameworks/backend/index.ts +241 -0
  302. package/templates/webapp/ssr-frameworks/frontend/dist/index.html +31 -0
  303. package/templates/webapp/ssr-hono/backend/index.ts +111 -0
  304. package/templates/webapp/ssr-hono/frontend/dist/index.html +12 -0
  305. package/templates/webapp/ssr-shop/README.md +80 -0
  306. package/templates/webapp/ssr-shop/backend/index.ts +491 -0
  307. package/templates/webapp/ssr-shop/db/rls.json +16 -0
  308. package/templates/webapp/ssr-shop/db/schema.sql +90 -0
  309. package/templates/webapp/ssr-shop/frontend/dist/index.html +12 -0
  310. package/templates/webapp/vanilla-static/frontend/dist/app.js +6 -0
  311. package/templates/webapp/vanilla-static/frontend/dist/index.html +19 -0
  312. package/templates/webapp/vanilla-static/frontend/dist/style.css +43 -0
@@ -0,0 +1,40 @@
1
+ /**
2
+ * 密钥脱敏工具 - 只显示指纹,不暴露完整密钥
3
+ */
4
+ import { createHash } from 'node:crypto';
5
+ /**
6
+ * 计算密钥指纹:sha256 前8字符 + 后4字符
7
+ * 格式:sha256:abcd1234...ef56
8
+ *
9
+ * 这是**展示层**的唯一加前缀处(whoami / instance / provision 直接输出它)。
10
+ * `introspectJwt().fingerprint` 返回的是同一指纹的裸值,前缀只在这里加一次。
11
+ */
12
+ export function computeFingerprint(key) {
13
+ const hash = createHash('sha256').update(key).digest('hex');
14
+ return `sha256:${hash.slice(0, 8)}...${hash.slice(-4)}`;
15
+ }
16
+ /**
17
+ * 脱敏 Authorization header
18
+ * 输入: "Bearer eyJhbGc..."
19
+ * 输出: "Bearer sha256:abcd1234...ef56"
20
+ */
21
+ export function maskAuthorizationHeader(header) {
22
+ if (!header.startsWith('Bearer ')) {
23
+ return header;
24
+ }
25
+ const token = header.slice(7);
26
+ const fingerprint = computeFingerprint(token);
27
+ return `Bearer ${fingerprint}`;
28
+ }
29
+ /**
30
+ * 脱敏任意字符串(如果看起来像 JWT)
31
+ * JWT 特征:包含两个点,三段 base64
32
+ */
33
+ export function maskIfJwt(value) {
34
+ const parts = value.split('.');
35
+ if (parts.length === 3 && parts.every(p => p.length > 0)) {
36
+ return computeFingerprint(value);
37
+ }
38
+ return value;
39
+ }
40
+ //# sourceMappingURL=masker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"masker.js","sourceRoot":"","sources":["../../src/credentials/masker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC;;;;;;GAMG;AACH,MAAM,UAAU,kBAAkB,CAAC,GAAW;IAC5C,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5D,OAAO,UAAU,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAClC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAC9B,MAAM,WAAW,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC9C,OAAO,UAAU,WAAW,EAAE,CAAC;AACjC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACzD,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Profile 管理器 - 多环境配置管理
3
+ */
4
+ export type ProfileMode = 'single-tenant' | 'multi-tenant';
5
+ /** Where a profile's instance came from: a customer's own instance (login) or a Zero-provisioned one. */
6
+ export type ProfileSource = 'login' | 'zero';
7
+ export interface BaasProfile {
8
+ name: string;
9
+ endpoint: string;
10
+ /** Canonical App origin supplied by the platform; never derived by the CLI. */
11
+ appEndpoint?: string;
12
+ tenantId?: string;
13
+ mode: ProfileMode;
14
+ /** Instance origin. Absent on legacy profiles (treated as 'login'). */
15
+ source?: ProfileSource;
16
+ /** Zero instance id (sbx_*), only when source === 'zero'. */
17
+ zeroInstanceId?: string;
18
+ /** Zero instance expiry (ISO 8601), only when source === 'zero'. */
19
+ expiresAt?: string;
20
+ /**
21
+ * 该 profile 是否绑定了平台管理凭据(dashboard Basic Auth)。仅是标记:口令本身
22
+ * 存在凭据存储的独立账目里,数据面命令读不到它。
23
+ */
24
+ adminCapable?: boolean;
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ }
28
+ interface ProfilesStore {
29
+ version: 1;
30
+ current: string;
31
+ profiles: Record<string, BaasProfile>;
32
+ }
33
+ /** 设置进程级 profile 覆盖(由 main.ts 的 preAction hook 调用)。 */
34
+ export declare function setCliProfileOverrideGlobal(profileName: string | undefined): void;
35
+ /** 读取进程级 profile 覆盖(供测试/诊断)。 */
36
+ export declare function getCliProfileOverrideGlobal(): string | undefined;
37
+ /**
38
+ * 判断被调用的命令是否会创建/覆盖 `--profile` 指定的 profile。
39
+ *
40
+ * @param commandPath 完整命令路径(如 `['profile','import']`),不含程序名。
41
+ * 只比叶子名会让将来任何同名子命令误获放行,故必须传完整路径。
42
+ */
43
+ export declare function isProfileCreatingCommand(commandPath: readonly string[]): boolean;
44
+ export declare class ProfileManager {
45
+ private homeDir;
46
+ private cliProfileOverride?;
47
+ private store;
48
+ constructor(homeDir?: string);
49
+ /**
50
+ * 设置 CLI profile 覆盖(来自 --profile flag)。
51
+ * 同时写入进程级变量,使其它命令实例(各自 new ProfileManager)也能看到。
52
+ */
53
+ setCliProfileOverride(profileName: string | undefined): void;
54
+ /** 生效的 --profile 覆盖:实例级优先,其次进程级。 */
55
+ private get effectiveCliProfileOverride();
56
+ /**
57
+ * 获取 profiles.json 路径
58
+ */
59
+ private getProfilesFilePath;
60
+ /**
61
+ * 加载 profiles store
62
+ */
63
+ load(): Promise<ProfilesStore>;
64
+ /**
65
+ * 保存 profiles store
66
+ */
67
+ private save;
68
+ /**
69
+ * 获取当前激活的 profile
70
+ * 优先级:--profile flag > BAAS_PROFILE env > store.current
71
+ */
72
+ getCurrentProfile(): Promise<BaasProfile | null>;
73
+ /**
74
+ * 列出所有 profiles
75
+ */
76
+ listProfiles(): Promise<BaasProfile[]>;
77
+ /**
78
+ * 获取指定 profile
79
+ */
80
+ getProfile(name: string): Promise<BaasProfile | null>;
81
+ /**
82
+ * 创建或更新 profile
83
+ */
84
+ setProfile(profile: BaasProfile): Promise<void>;
85
+ /**
86
+ * 切换当前 profile
87
+ */
88
+ useProfile(name: string): Promise<void>;
89
+ /**
90
+ * 删除 profile
91
+ */
92
+ removeProfile(name: string): Promise<boolean>;
93
+ }
94
+ export {};
95
+ //# sourceMappingURL=profile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.d.ts","sourceRoot":"","sources":["../../src/credentials/profile.ts"],"names":[],"mappings":"AAAA;;GAEG;AAOH,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,cAAc,CAAC;AAE3D,yGAAyG;AACzG,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,MAAM,CAAC;AAE7C,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,WAAW,CAAC;IAClB,uEAAuE;IACvE,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB,6DAA6D;IAC7D,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oEAAoE;IACpE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,aAAa;IACrB,OAAO,EAAE,CAAC,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;CACvC;AAYD,uDAAuD;AACvD,wBAAgB,2BAA2B,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAEjF;AAED,gCAAgC;AAChC,wBAAgB,2BAA2B,IAAI,MAAM,GAAG,SAAS,CAEhE;AAgBD;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAMhF;AAED,qBAAa,cAAc;IACzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,kBAAkB,CAAC,CAAS;IACpC,OAAO,CAAC,KAAK,CAA8B;gBAE/B,OAAO,CAAC,EAAE,MAAM;IAI5B;;;OAGG;IACH,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAK5D,oCAAoC;IACpC,OAAO,KAAK,2BAA2B,GAEtC;IAED;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAI3B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,aAAa,CAAC;IA2BpC;;OAEG;YACW,IAAI;IAYlB;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAsCtD;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAK5C;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAK3D;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBrD;;OAEG;IACG,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAW7C;;OAEG;IACG,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAiBpD"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Profile 管理器 - 多环境配置管理
3
+ */
4
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
5
+ import { existsSync } from 'node:fs';
6
+ import { homedir } from 'node:os';
7
+ import { join } from 'node:path';
8
+ /**
9
+ * Profile 管理器
10
+ *
11
+ * 存储路径:~/.baas/profiles.json
12
+ * 优先级:--profile flag > BAAS_PROFILE env > store.current
13
+ */
14
+ // 进程级 --profile 覆盖:各命令实现自己 new ProfileManager(),实例字段无法跨实例共享,
15
+ // 因此用模块级变量承载(仅本进程生效,绝不写回 profiles.json)。
16
+ let processCliProfileOverride;
17
+ /** 设置进程级 profile 覆盖(由 main.ts 的 preAction hook 调用)。 */
18
+ export function setCliProfileOverrideGlobal(profileName) {
19
+ processCliProfileOverride = profileName;
20
+ }
21
+ /** 读取进程级 profile 覆盖(供测试/诊断)。 */
22
+ export function getCliProfileOverrideGlobal() {
23
+ return processCliProfileOverride;
24
+ }
25
+ /**
26
+ * 会「写入 --profile 所指 profile」的命令,按完整命令路径匹配。
27
+ *
28
+ * 对这些命令来说,profile 名不存在恰恰是前提(它们正要创建它),所以 main.ts 的
29
+ * preAction 钩子不能对其做存在性硬校验;其余命令一律保持响亮失败,否则就退回了
30
+ * `--profile` 曾被静默忽略、写操作跨实例误落的旧缺陷。
31
+ */
32
+ const PROFILE_CREATING_COMMANDS = [
33
+ ['login'],
34
+ ['profile', 'import'],
35
+ // `tenant login` 可以把管理凭据绑定到一个尚不存在的 profile(管理员常在新机器上先做这一步)
36
+ ['tenant', 'login'],
37
+ ];
38
+ /**
39
+ * 判断被调用的命令是否会创建/覆盖 `--profile` 指定的 profile。
40
+ *
41
+ * @param commandPath 完整命令路径(如 `['profile','import']`),不含程序名。
42
+ * 只比叶子名会让将来任何同名子命令误获放行,故必须传完整路径。
43
+ */
44
+ export function isProfileCreatingCommand(commandPath) {
45
+ return PROFILE_CREATING_COMMANDS.some((candidate) => candidate.length === commandPath.length &&
46
+ candidate.every((segment, index) => segment === commandPath[index]));
47
+ }
48
+ export class ProfileManager {
49
+ homeDir;
50
+ cliProfileOverride; // --profile flag
51
+ store = null;
52
+ constructor(homeDir) {
53
+ this.homeDir = homeDir ?? join(homedir(), '.baas');
54
+ }
55
+ /**
56
+ * 设置 CLI profile 覆盖(来自 --profile flag)。
57
+ * 同时写入进程级变量,使其它命令实例(各自 new ProfileManager)也能看到。
58
+ */
59
+ setCliProfileOverride(profileName) {
60
+ this.cliProfileOverride = profileName;
61
+ processCliProfileOverride = profileName;
62
+ }
63
+ /** 生效的 --profile 覆盖:实例级优先,其次进程级。 */
64
+ get effectiveCliProfileOverride() {
65
+ return this.cliProfileOverride ?? processCliProfileOverride;
66
+ }
67
+ /**
68
+ * 获取 profiles.json 路径
69
+ */
70
+ getProfilesFilePath() {
71
+ return join(this.homeDir, 'profiles.json');
72
+ }
73
+ /**
74
+ * 加载 profiles store
75
+ */
76
+ async load() {
77
+ if (this.store) {
78
+ return this.store;
79
+ }
80
+ const filePath = this.getProfilesFilePath();
81
+ if (!existsSync(filePath)) {
82
+ this.store = { version: 1, current: '', profiles: {} };
83
+ return this.store;
84
+ }
85
+ try {
86
+ const content = await readFile(filePath, 'utf-8');
87
+ const data = JSON.parse(content);
88
+ if (data.version !== 1) {
89
+ throw new Error(`Unsupported profiles file version: ${data.version}`);
90
+ }
91
+ this.store = data;
92
+ return this.store;
93
+ }
94
+ catch (err) {
95
+ throw new Error(`Failed to read profiles file: ${err instanceof Error ? err.message : String(err)}`);
96
+ }
97
+ }
98
+ /**
99
+ * 保存 profiles store
100
+ */
101
+ async save(store) {
102
+ if (!existsSync(this.homeDir)) {
103
+ await mkdir(this.homeDir, { mode: 0o700, recursive: true });
104
+ }
105
+ const filePath = this.getProfilesFilePath();
106
+ const content = JSON.stringify(store, null, 2);
107
+ await writeFile(filePath, content, { mode: 0o644 });
108
+ this.store = store;
109
+ }
110
+ /**
111
+ * 获取当前激活的 profile
112
+ * 优先级:--profile flag > BAAS_PROFILE env > store.current
113
+ */
114
+ async getCurrentProfile() {
115
+ const store = await this.load();
116
+ // 1. CLI --profile flag
117
+ const cliOverride = this.effectiveCliProfileOverride;
118
+ if (cliOverride) {
119
+ const profile = store.profiles[cliOverride];
120
+ if (!profile) {
121
+ throw new Error(`Profile '${cliOverride}' not found (from --profile flag)`);
122
+ }
123
+ return profile;
124
+ }
125
+ // 2. BAAS_PROFILE 环境变量
126
+ const envProfile = process.env.BAAS_PROFILE;
127
+ if (envProfile) {
128
+ const profile = store.profiles[envProfile];
129
+ if (!profile) {
130
+ throw new Error(`Profile '${envProfile}' not found (from BAAS_PROFILE env)`);
131
+ }
132
+ return profile;
133
+ }
134
+ // 3. store.current
135
+ if (store.current) {
136
+ const profile = store.profiles[store.current];
137
+ if (!profile) {
138
+ // current 指向不存在的 profile,清除它
139
+ store.current = '';
140
+ await this.save(store);
141
+ return null;
142
+ }
143
+ return profile;
144
+ }
145
+ return null;
146
+ }
147
+ /**
148
+ * 列出所有 profiles
149
+ */
150
+ async listProfiles() {
151
+ const store = await this.load();
152
+ return Object.values(store.profiles);
153
+ }
154
+ /**
155
+ * 获取指定 profile
156
+ */
157
+ async getProfile(name) {
158
+ const store = await this.load();
159
+ return store.profiles[name] ?? null;
160
+ }
161
+ /**
162
+ * 创建或更新 profile
163
+ */
164
+ async setProfile(profile) {
165
+ const store = await this.load();
166
+ const now = new Date().toISOString();
167
+ if (store.profiles[profile.name]) {
168
+ // 更新
169
+ profile.updatedAt = now;
170
+ }
171
+ else {
172
+ // 创建
173
+ profile.createdAt = now;
174
+ profile.updatedAt = now;
175
+ }
176
+ store.profiles[profile.name] = profile;
177
+ await this.save(store);
178
+ }
179
+ /**
180
+ * 切换当前 profile
181
+ */
182
+ async useProfile(name) {
183
+ const store = await this.load();
184
+ if (!store.profiles[name]) {
185
+ throw new Error(`Profile '${name}' not found`);
186
+ }
187
+ store.current = name;
188
+ await this.save(store);
189
+ }
190
+ /**
191
+ * 删除 profile
192
+ */
193
+ async removeProfile(name) {
194
+ const store = await this.load();
195
+ if (!store.profiles[name]) {
196
+ return false;
197
+ }
198
+ delete store.profiles[name];
199
+ // 如果删除的是当前 profile,清除 current
200
+ if (store.current === name) {
201
+ store.current = '';
202
+ }
203
+ await this.save(store);
204
+ return true;
205
+ }
206
+ }
207
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../../src/credentials/profile.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * 租户一致性守卫 - 验证 profile 和 JWT 的 tenant_id 一致
3
+ */
4
+ import type { BaasProfile } from './profile.js';
5
+ import type { IntrospectedJwt } from './jwt-introspect.js';
6
+ /**
7
+ * 验证 profile 和 JWT 的 tenant_id 一致性
8
+ *
9
+ * 规则:
10
+ * - 多租户模式:profile.tenantId == anonJwt.tenantId == serviceJwt.tenantId
11
+ * - 单租户模式:profile.tenantId 为空,JWT 的 tenant_id 也应为空(或不存在)
12
+ *
13
+ * @throws Error 如果不一致
14
+ */
15
+ export declare function validateTenantConsistency(profile: BaasProfile, anonJwt: IntrospectedJwt, serviceJwt: IntrospectedJwt): void;
16
+ //# sourceMappingURL=tenant-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-guard.d.ts","sourceRoot":"","sources":["../../src/credentials/tenant-guard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAE3D;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,WAAW,EACpB,OAAO,EAAE,eAAe,EACxB,UAAU,EAAE,eAAe,GAC1B,IAAI,CAwDN"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * 租户一致性守卫 - 验证 profile 和 JWT 的 tenant_id 一致
3
+ */
4
+ /**
5
+ * 验证 profile 和 JWT 的 tenant_id 一致性
6
+ *
7
+ * 规则:
8
+ * - 多租户模式:profile.tenantId == anonJwt.tenantId == serviceJwt.tenantId
9
+ * - 单租户模式:profile.tenantId 为空,JWT 的 tenant_id 也应为空(或不存在)
10
+ *
11
+ * @throws Error 如果不一致
12
+ */
13
+ export function validateTenantConsistency(profile, anonJwt, serviceJwt) {
14
+ const profileTenant = profile.tenantId;
15
+ const anonTenant = anonJwt.payload.tenant_id;
16
+ const serviceTenant = serviceJwt.payload.tenant_id;
17
+ // 多租户模式
18
+ if (profile.mode === 'multi-tenant') {
19
+ if (!profileTenant) {
20
+ throw new Error('Error: multi-tenant profile must have tenantId');
21
+ }
22
+ if (anonTenant !== profileTenant) {
23
+ throw new Error(`Error: tenant_id mismatch. Profile: ${profileTenant}, Anon JWT: ${anonTenant ?? 'none'}. ` +
24
+ `Ensure you pasted the correct keys for this tenant.`);
25
+ }
26
+ if (serviceTenant !== profileTenant) {
27
+ throw new Error(`Error: tenant_id mismatch. Profile: ${profileTenant}, Service JWT: ${serviceTenant ?? 'none'}. ` +
28
+ `Ensure you pasted the correct keys for this tenant.`);
29
+ }
30
+ }
31
+ // 单租户模式
32
+ if (profile.mode === 'single-tenant') {
33
+ if (profileTenant) {
34
+ throw new Error('Error: single-tenant profile must not have tenantId');
35
+ }
36
+ // 单租户模式下,JWT 不应该包含 tenant_id(或者 tenant_id 为空字符串)
37
+ if (anonTenant && anonTenant !== '') {
38
+ throw new Error(`Error: single-tenant profile but anon JWT has tenant_id: ${anonTenant}. ` +
39
+ `This key is for multi-tenant mode.`);
40
+ }
41
+ if (serviceTenant && serviceTenant !== '') {
42
+ throw new Error(`Error: single-tenant profile but service JWT has tenant_id: ${serviceTenant}. ` +
43
+ `This key is for multi-tenant mode.`);
44
+ }
45
+ }
46
+ // 两把 key 的 tenant_id 必须一致(无论单租户还是多租户)
47
+ if (anonTenant !== serviceTenant) {
48
+ throw new Error(`Error: anon and service JWT have different tenant_id. ` +
49
+ `Anon: ${anonTenant ?? 'none'}, Service: ${serviceTenant ?? 'none'}. ` +
50
+ `Ensure both keys are for the same tenant.`);
51
+ }
52
+ }
53
+ //# sourceMappingURL=tenant-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-guard.js","sourceRoot":"","sources":["../../src/credentials/tenant-guard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;;;;;GAQG;AACH,MAAM,UAAU,yBAAyB,CACvC,OAAoB,EACpB,OAAwB,EACxB,UAA2B;IAE3B,MAAM,aAAa,GAAG,OAAO,CAAC,QAAQ,CAAC;IACvC,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC;IAC7C,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC;IAEnD,QAAQ;IACR,IAAI,OAAO,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QAED,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CACb,uCAAuC,aAAa,eAAe,UAAU,IAAI,MAAM,IAAI;gBAC3F,qDAAqD,CACtD,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,KAAK,aAAa,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,uCAAuC,aAAa,kBAAkB,aAAa,IAAI,MAAM,IAAI;gBACjG,qDAAqD,CACtD,CAAC;QACJ,CAAC;IACH,CAAC;IAED,QAAQ;IACR,IAAI,OAAO,CAAC,IAAI,KAAK,eAAe,EAAE,CAAC;QACrC,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QAED,iDAAiD;QACjD,IAAI,UAAU,IAAI,UAAU,KAAK,EAAE,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,4DAA4D,UAAU,IAAI;gBAC1E,oCAAoC,CACrC,CAAC;QACJ,CAAC;QAED,IAAI,aAAa,IAAI,aAAa,KAAK,EAAE,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,+DAA+D,aAAa,IAAI;gBAChF,oCAAoC,CACrC,CAAC;QACJ,CAAC;IACH,CAAC;IAED,sCAAsC;IACtC,IAAI,UAAU,KAAK,aAAa,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,wDAAwD;YACxD,SAAS,UAAU,IAAI,MAAM,cAAc,aAAa,IAAI,MAAM,IAAI;YACtE,2CAA2C,CAC5C,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * TTY 守卫 - 防止 agent 执行敏感命令
3
+ */
4
+ /**
5
+ * 断言当前运行在交互式 TTY 中
6
+ * @param isTTY - 可选参数,用于测试。如果不提供,则从 process.stdin.isTTY 读取
7
+ * @param ciEnv - 可选参数,用于测试。如果不提供,则从 process.env.CI 读取
8
+ * @throws Error 如果非 TTY 环境
9
+ */
10
+ export declare function assertTty(isTTY?: boolean, ciEnv?: string): void;
11
+ /**
12
+ * 从 stdin 按行读取密钥/口令类输入。
13
+ *
14
+ * 存在的理由:敏感值绝不能走 argv(会进 shell history 与进程列表)。login 与
15
+ * tenant login 都需要"两行管道输入",此前各自实现了一份,统一到这里。
16
+ *
17
+ * @param expected 期望的行数
18
+ * @param label 报错里对各行内容的说明(保持调用方的既有文案可辨识)
19
+ */
20
+ export declare function readStdinLines(expected: number, label: string): Promise<string[]>;
21
+ /**
22
+ * 断言命令行参数中不包含密钥参数
23
+ * 防止通过 argv 传递密钥(会出现在 shell history 中)
24
+ *
25
+ * @param argv - 命令行参数数组
26
+ * @throws Error 如果发现密钥参数
27
+ */
28
+ export declare function assertNoKeyArgs(argv: string[]): void;
29
+ //# sourceMappingURL=tty-guard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tty-guard.d.ts","sourceRoot":"","sources":["../../src/credentials/tty-guard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAkB/D;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAmBvF;AACD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,IAAI,CAsBpD"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * TTY 守卫 - 防止 agent 执行敏感命令
3
+ */
4
+ /**
5
+ * 断言当前运行在交互式 TTY 中
6
+ * @param isTTY - 可选参数,用于测试。如果不提供,则从 process.stdin.isTTY 读取
7
+ * @param ciEnv - 可选参数,用于测试。如果不提供,则从 process.env.CI 读取
8
+ * @throws Error 如果非 TTY 环境
9
+ */
10
+ export function assertTty(isTTY, ciEnv) {
11
+ // 检查 stdin 是否是 TTY
12
+ const actualIsTTY = isTTY !== undefined ? isTTY : process.stdin.isTTY;
13
+ if (!actualIsTTY) {
14
+ throw new Error('Error: pxbaas login requires an interactive TTY. ' +
15
+ 'Use --anon-key-stdin and --service-key-stdin for piped input.');
16
+ }
17
+ // 额外防护:CI 环境
18
+ const actualCI = ciEnv !== undefined ? ciEnv : process.env.CI;
19
+ if (actualCI === 'true' || actualCI === '1') {
20
+ throw new Error('Error: pxbaas login is disabled in CI environments. ' +
21
+ 'Use --anon-key-stdin and --service-key-stdin for non-interactive input.');
22
+ }
23
+ }
24
+ /**
25
+ * 从 stdin 按行读取密钥/口令类输入。
26
+ *
27
+ * 存在的理由:敏感值绝不能走 argv(会进 shell history 与进程列表)。login 与
28
+ * tenant login 都需要"两行管道输入",此前各自实现了一份,统一到这里。
29
+ *
30
+ * @param expected 期望的行数
31
+ * @param label 报错里对各行内容的说明(保持调用方的既有文案可辨识)
32
+ */
33
+ export async function readStdinLines(expected, label) {
34
+ const data = await new Promise((resolvePromise, rejectPromise) => {
35
+ let buffer = '';
36
+ process.stdin.setEncoding('utf8');
37
+ process.stdin.on('readable', () => {
38
+ let chunk;
39
+ while ((chunk = process.stdin.read()) !== null) {
40
+ buffer += chunk;
41
+ }
42
+ });
43
+ process.stdin.on('end', () => resolvePromise(buffer));
44
+ process.stdin.on('error', rejectPromise);
45
+ });
46
+ const lines = data.split('\n').map((line) => line.trim());
47
+ if (lines.length < expected) {
48
+ throw new Error(`Expected ${expected} lines from stdin: ${label}`);
49
+ }
50
+ return lines;
51
+ }
52
+ /**
53
+ * 断言命令行参数中不包含密钥参数
54
+ * 防止通过 argv 传递密钥(会出现在 shell history 中)
55
+ *
56
+ * @param argv - 命令行参数数组
57
+ * @throws Error 如果发现密钥参数
58
+ */
59
+ export function assertNoKeyArgs(argv) {
60
+ const forbiddenArgs = [
61
+ '--anon-key',
62
+ '--service-key',
63
+ '--token',
64
+ // 平台管理凭据同样不得进 argv(会留在 shell history 与进程列表里)
65
+ '--dashboard-user',
66
+ '--dashboard-password',
67
+ '--admin-password',
68
+ ];
69
+ for (const arg of argv) {
70
+ // 检查 --anon-key=value 或 --anon-key value 形式
71
+ for (const forbidden of forbiddenArgs) {
72
+ if (arg === forbidden || arg.startsWith(`${forbidden}=`)) {
73
+ throw new Error(`Error: passing keys via argv is forbidden (${arg}). ` +
74
+ `Use ${forbidden}-stdin or environment variables.`);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ //# sourceMappingURL=tty-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tty-guard.js","sourceRoot":"","sources":["../../src/credentials/tty-guard.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,KAAe,EAAE,KAAc;IACvD,mBAAmB;IACnB,MAAM,WAAW,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IACtE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,mDAAmD;YACnD,+DAA+D,CAChE,CAAC;IACJ,CAAC;IAED,aAAa;IACb,MAAM,QAAQ,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;IAC9D,IAAI,QAAQ,KAAK,MAAM,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CACb,sDAAsD;YACtD,yEAAyE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,QAAgB,EAAE,KAAa;IAClE,MAAM,IAAI,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,cAAc,EAAE,aAAa,EAAE,EAAE;QACvE,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAClC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,EAAE;YAChC,IAAI,KAAoB,CAAC;YACzB,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;gBAC/C,MAAM,IAAI,KAAK,CAAC;YAClB,CAAC;QACH,CAAC,CAAC,CAAC;QACH,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;QACtD,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;IAC1D,IAAI,KAAK,CAAC,MAAM,GAAG,QAAQ,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CAAC,YAAY,QAAQ,sBAAsB,KAAK,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AACD;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,IAAc;IAC5C,MAAM,aAAa,GAAG;QACpB,YAAY;QACZ,eAAe;QACf,SAAS;QACT,6CAA6C;QAC7C,kBAAkB;QAClB,sBAAsB;QACtB,kBAAkB;KACnB,CAAC;IAEF,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,4CAA4C;QAC5C,KAAK,MAAM,SAAS,IAAI,aAAa,EAAE,CAAC;YACtC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,SAAS,GAAG,CAAC,EAAE,CAAC;gBACzD,MAAM,IAAI,KAAK,CACb,8CAA8C,GAAG,KAAK;oBACtD,OAAO,SAAS,kCAAkC,CACnD,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}