@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,186 @@
1
+ ---
2
+ name: pxbaas-cli
3
+ description: "Use the PolarDB-X BaaS CLI (`pxbaas`) to work with a PolarDB-X BaaS / MySQL-Supabase instance: run SQL and inspect tables/schema (`db`), read/write rows PostgREST-style (`data`, `rest`), deploy/list/delete Edge Functions (`functions`), scaffold-deploy-publish Webapps and share links (`app`), storage objects, auth users, type generation, claim a free disposable instance (`provision`), and - for instance operators - administer tenants and hand out per-tenant keys (`tenant probe/ls/create/keys/repair-keys`, access bundles). Trigger on pxbaas commands, BaaS SQL or table questions, function/webapp deploy, storage or users, gen types, provisioning, multi-tenant login, and 401/403 errors. Agent rules: never run `pxbaas login` (TTY-only); `provision` and `profile import <env-file>` are agent-runnable; always pass `--json`; never print or request plaintext keys; never create a tenant without explicit user confirmation."
4
+ ---
5
+
6
+ # pxbaas-cli
7
+
8
+ Usage guide for `pxbaas`, the customer-facing CLI of **PolarDB-X BaaS** (the MySQL port of Supabase).
9
+
10
+ This skill covers **data-plane consumption**: the platform is already deployed by operators, and customers use `pxbaas` to query and operate it.
11
+ Platform deployment / component ops are **out of scope** — see the `supabase-dev` skill for those.
12
+
13
+ ## What is PolarDB-X BaaS (Supabase)?
14
+
15
+ Supabase is an open-source Backend-as-a-Service (a Firebase alternative) providing Auth, a PostgREST-style REST API, Realtime, Storage, Edge Functions, and a Studio console.
16
+ **PolarDB-X BaaS** replaces the PostgreSQL backend with **MySQL 8.0+ / PolarDB-X** while keeping the wire protocol compatible — the official `supabase-js` client works unmodified.
17
+
18
+ All requests go through a single Kong gateway (port **8000**). Key path prefixes:
19
+
20
+ | Component | Path prefix | Note |
21
+ |---|---|---|
22
+ | MysqlREST | `/rest/v1/` | PostgREST-compatible REST over MySQL |
23
+ | Auth (GoTrue) | `/auth/v1/` | Users, JWT, OAuth |
24
+ | Storage | `/storage/v1/` | Files, S3/OSS backend |
25
+ | Realtime | `/realtime/v1/` | WebSocket subscriptions |
26
+ | Edge Functions | `/functions/v1/` | Serverless TS/JS and immutable App candidates |
27
+ | Apps | `/apps/{mount}/` | Capability-gated Webapp frontend; backend API at `/apps/{mount}/api/*` |
28
+ | PG-Meta | `/pg/` | DB metadata — **admin only** |
29
+ | Management API | `/v1/projects/*` | Deploy/manage — **admin only** |
30
+
31
+ **Single-tenant vs multi-tenant:** in multi-tenant mode every request must carry a valid `tenant_id` (JWT claim and/or `X-Tenant-Id`), keys are per-tenant, and global keys are rejected. The `pxbaas` CLI handles this for you via the profile's `tenantId`.
32
+ → For the authoritative, always-in-sync API details (incl. multi-tenant behavior and limitations), fetch the live reference: **`GET ${endpoint}/docs`** (no auth). See `references/api-reference.md`.
33
+ → Deploying apps on a **multi-tenant** instance (tenant provisioning, the three credential tiers, where RLS metadata really lives, cross-tenant acceptance): see `references/multi-tenant-apps.md`.
34
+
35
+ ## When to use this skill
36
+
37
+ - Query/operate BaaS tables, data, Edge Functions, storage, or users from the command line
38
+ - Run SQL, inspect table schema, list tables, generate TypeScript types
39
+ - Deploy / list / delete an Edge Function
40
+ - Upload / download / delete storage objects
41
+ - Diagnose `pxbaas` connection, 401/403, credential, or tenant problems
42
+
43
+ ## Mental model (understand these 4 concepts first)
44
+
45
+ 1. **profile** — one environment config (endpoint + tenantId + role keys), stored in the OS keyring. You can have several; switch with `--profile <name>` or `pxbaas profile use`.
46
+ 2. **role** — `anon` (read / RLS-constrained) vs `service_role` (bypasses RLS, admin-level). Commands have different default roles; see the command map.
47
+ 3. **tenant** — the tenant boundary in multi-tenant mode. The CLI validates that the key's `tenant_id` matches the profile; cross-tenant access is rejected.
48
+ 4. **capability URLs** — `pxbaas status --json` returns the real URL of each capability (rest/auth/storage/functions/meta); the starting point for troubleshooting.
49
+
50
+ ## Non-negotiable rules
51
+
52
+ | # | Rule | Detail |
53
+ |---|---|---|
54
+ | **1** | **NEVER run `pxbaas login`** | It requires an interactive TTY; agents cannot complete it. Credentials are provisioned by a human. If not logged in, **ask the user to run `pxbaas login`** — do not attempt it and do not ask for plaintext keys. **Exception:** `pxbaas provision` IS agent-runnable (keys come from Zero over TLS and are stored without being shown) — see `references/provision.md`. |
55
+ | **2** | **Pass `--json` for anything you parse** | Status queries, remote operations, and any command whose result you read MUST use `--json` (parse JSON, never human-readable text). Pure local scaffolding, shell completion, and file-output commands (e.g. `gen types --output <file>`) are human-facing — `--json` is optional there. |
56
+ | **3** | **You cannot see plaintext keys** | Output shows only fingerprints (sha256 first 8 + last 4). Never expect, echo, or reconstruct a plaintext anon/service key. |
57
+ | **4** | **Confirm destructive ops first** | Some commands gate themselves (`--dry-run`/`--yes` on `db push`, `app db-init`, `data delete`; `--confirm` on `app remove`, `app destroy`, `instance release`, `app share revoke`, `skill remove`, `tenant create`, `tenant repair-keys`). **Many do not** — `db create-table` / `db add-column`, `functions deploy` / `delete`, `storage rm` / `mv` / `cp` overwrite, `auth users delete`, `rest` writes execute immediately. For those, YOU are the gate: restate target, impact and reversibility, then get explicit consent. See `references/safety-and-two-phase.md`. |
58
+ | **5** | **Respect role & tenant isolation** | Prefer `anon` for reads; explain when `service_role` is needed (it bypasses RLS). Never mix credentials across profiles. |
59
+
60
+ ## First-run discovery
61
+
62
+ Run these (all read-only) to establish state before doing anything else:
63
+
64
+ ```bash
65
+ pxbaas guide # 0. printable end-to-end develop/deploy/verify/share workflow (no auth needed)
66
+ pxbaas status --json # 1. capability URLs; confirm endpoint and availability
67
+ pxbaas doctor --json # 2. health: connectivity, JWT validity, expiry, tenant status
68
+ pxbaas whoami --json # 3. current profile / tenant / role / key fingerprints
69
+ ```
70
+
71
+ If not logged in or `doctor` reports a failure → back to Rule 1: ask the user to run `pxbaas login`; do not work around it.
72
+
73
+ ## Command map (full surface)
74
+
75
+ Legend — **R** = read/safe · **W** = write · **D** = destructive (consent required). "Details" = which reference to open.
76
+
77
+ | Command | Default role | R/W/D | Details |
78
+ |---|---|---|---|
79
+ | `login` (human TTY only) | — | special | auth-and-credentials.md |
80
+ | `profile import <env-file>` (agent-runnable; single-tenant, or multi-tenant when the file carries `TENANT_*` keys) | — | W (local) | auth-and-credentials.md |
81
+ | `logout` | — | W (local) | auth-and-credentials.md |
82
+ | `whoami` | — | R | auth-and-credentials.md |
83
+ | `status` | — | R | auth-and-credentials.md |
84
+ | `doctor` | — | R | troubleshooting.md |
85
+ | `profile ls` | — | R | auth-and-credentials.md |
86
+ | `profile use <name>` | — | W (local) | auth-and-credentials.md |
87
+ | `profile rm <name>` | — | D (local) | auth-and-credentials.md |
88
+ | `db query <sql>` | anon | R/W | db-and-meta.md |
89
+ | `db tables` | service_role | R | db-and-meta.md |
90
+ | `db schema <table>` | service_role | R | db-and-meta.md |
91
+ | `db create-table <name>` | service_role | **D** (DDL) | db-and-meta.md |
92
+ | `db add-column <table> <column>` | service_role | **D** (DDL) | db-and-meta.md |
93
+ | `gen types` | — | R | db-and-meta.md |
94
+ | `data select <table>` | anon | R | data-postgrest.md |
95
+ | `data insert <table>` | anon | W | data-postgrest.md |
96
+ | `data update <table>` | anon | W | data-postgrest.md |
97
+ | `data delete <table>` | anon | **D** | data-postgrest.md |
98
+ | `rest <method> <path>` | anon | R/W/D | data-postgrest.md |
99
+ | `functions new <slug>` | — | local | edge-functions.md |
100
+ | `functions deploy <slug>` | service_role | **D/W** | edge-functions.md |
101
+ | `functions list` | service_role | R | edge-functions.md |
102
+ | `functions delete <slug>` | service_role | **D** | edge-functions.md |
103
+ | `storage ls [path]` | — | R | storage.md |
104
+ | `storage cp <src> <dst>` | — | W | storage.md |
105
+ | `storage mv <src> <dst>` | — | W | storage.md |
106
+ | `storage rm <path>` | — | **D** | storage.md |
107
+ | `auth users list` | service_role | R | auth-and-credentials.md |
108
+ | `auth users get <userId>` | service_role | R | auth-and-credentials.md |
109
+ | `auth users create` | service_role | W | auth-and-credentials.md |
110
+ | `auth users delete <userId>` | service_role | **D** | auth-and-credentials.md |
111
+ | `auth users invite <email>` | service_role | W | auth-and-credentials.md |
112
+ | `completion <shell>` | — | R (local) | (this file) |
113
+ | `guide` | — | R (local, no auth) | (this file) |
114
+ | `tenant login` / `tenant logout` | dashboard Basic | W (local) | tenant-admin.md |
115
+ | `tenant probe` / `tenant ls` / `tenant handoffs` | dashboard Basic | R | tenant-admin.md |
116
+ | `tenant create [id]` | dashboard Basic | **D/W** (provisions db, account, GRANT, bucket, quota) | tenant-admin.md |
117
+ | `tenant keys <id>` | dashboard Basic | W (local; writes keyring or 0600 bundle) | tenant-admin.md |
118
+ | `tenant repair-keys` | dashboard Basic | W (`--confirm`) | tenant-admin.md |
119
+ | `provision` (agent-runnable) | — | W (local+remote) | provision.md |
120
+ | `instance list` / `instance current` | — | R | provision.md |
121
+ | `instance credentials <id>` | — | R (`--reveal` for dashboard pw) | provision.md |
122
+ | `instance release <id>` | — | **D** (two-phase `--confirm`) | provision.md |
123
+ | `instance whitelist get` / `instance whitelist add <ips>` | — | R / W (**Zero instances only**; append-only, `--dry-run` to preview) | provision.md |
124
+ | `app new <name>` | — | local | app-deploy.md |
125
+ | `app capabilities` | service_role | R | app-deploy.md |
126
+ | `app deploy <name>` | service_role | **D/W** | app-deploy.md |
127
+ | `app publish <name>` / `app rollback <name>` / `app unpublish <name>` | service_role | **D/W** | app-deploy.md |
128
+ | `app verify <name>` / `app url <name>` | — | R | app-deploy.md |
129
+ | `app list` / `app templates` | service_role | R | app-deploy.md |
130
+ | `app remove <name>` | service_role | **D** (`--confirm`; legacy `spa/api/mpa` only) | app-deploy.md |
131
+ | `app destroy <name>` | service_role | **D** (two-phase `--confirm`; webapp only; deletes edge funcs + mount, **keeps DB tables**) | app-deploy.md |
132
+
133
+ For provisioning / multi-instance selection see **provision.md**; for the `pxbaas app` commands see **app-deploy.md**; for tenant provisioning and handing per-tenant keys to end users see **tenant-admin.md** (operator-only surface). For how to **write** edge-function webapp code (Deno runtime contract, guardrails, templates, raw deploy paths), use the companion **`pxbaas-app-spec` skill**. For the live platform API beyond the CLI (all endpoints, multi-tenant rules, error codes, limitations), see **api-reference.md** (`GET ${endpoint}/docs`).
134
+
135
+ ## Natural language → command
136
+
137
+ ```
138
+ "how do I develop and deploy an app" → pxbaas guide (follow it; the bundled skills carry the details)
139
+ "show the schema of todos" → pxbaas db schema todos --json
140
+ "what tables are there" → pxbaas db tables --json
141
+ "count the users" → pxbaas db query "SELECT count(*) FROM users" --json
142
+ "get order id=1" → pxbaas data select orders --filter "id=eq.1" --json
143
+ "generate TS types" → pxbaas gen types --output types.ts --json
144
+ "list deployed functions" → pxbaas functions list --json
145
+ "insert a row" → confirm first → pxbaas data insert <table> --values '{...}' --json
146
+ "deploy this function" → confirm first → pxbaas functions deploy <slug> --json
147
+ "delete this object" → confirm first → pxbaas storage rm <bucket/path> --json
148
+ "I need a BaaS instance" → pxbaas provision --json (free 15-day Zero instance; agent-runnable)
149
+ "which instance am I on" → pxbaas instance current --json (or pxbaas whoami --json)
150
+ "show/extend my instance whitelist" → pxbaas instance whitelist get --json · pxbaas instance whitelist add <ip,cidr> --json (Zero instances only; append-only)
151
+ "deploy this demo webapp" → confirm first → pxbaas app deploy <name> --json
152
+ "give me a shareable demo URL" → pxbaas app url <name> --json
153
+ "published/shared but they can't open it" → IP-whitelist gate: pxbaas instance whitelist add <their-ip> --json (Zero instance) · purchased instance: add the recipient IP via the cloud console/control plane (CLI whitelist is Zero-only)
154
+ "destroy/delete this webapp" → confirm first → pxbaas app destroy <name> --confirm --json (removes edge funcs + mount; DB tables kept)
155
+ "can't connect / error" → pxbaas doctor --json; if credentials missing, ask user to run pxbaas login
156
+ "env says no tenant-level keys" → read the guidance it prints; if the user operates the instance: pxbaas tenant login → tenant ls → tenant keys <id> --as-profile (never create a tenant without asking)
157
+ "give this tenant to a new user" → pxbaas tenant keys <id> --bundle ./<id>.pxbaas.env, then send the printed handoff note (contains fingerprints, not keys)
158
+ ```
159
+
160
+ ## What NOT to do
161
+
162
+ - **NEVER run `pxbaas login`** — it needs an interactive TTY. Ask the user to log in instead.
163
+ - **NEVER expect or echo plaintext keys** — output is fingerprint-only; never ask the user for a raw key to build a command.
164
+ - **NEVER run `storage rm` / `functions delete` / `db create-table` / `db add-column` / `rest` writes / `auth users delete` without previewing first** and getting explicit user consent — those have **no** gate. `data delete`, `db push`, `app db-init`, `app destroy`, `instance release`, `tenant create` and `tenant repair-keys` do gate themselves; satisfy their `--yes`/`--confirm` only **after** the user agreed.
165
+ - **NEVER write PostgreSQL SQL in `db query`** — the backend is MySQL/PolarDB-X (use `CAST(x AS t)`, backticks, `JSON_EXTRACT`, `UUID()`, not `::`, `"col"`, `->>`, `gen_random_uuid()`).
166
+ - **NEVER assume an API listed in `/docs` is available via the CLI** — `/docs` covers the whole platform including admin APIs (PG-Meta, Management API) and tenant lifecycle; the CLI wraps only the customer data-plane subset in the command map above.
167
+ - **NEVER mix credentials across profiles** or target another tenant; the CLI enforces tenant isolation.
168
+ - **NEVER write multi-tenant RLS policies into a tenant DB's `_mysqlrest_rls_*` copies, or with `table_schema='public'`** — the authoritative store is the central `supabase` DB keyed by the tenant database name, and a wrong value fails **silently** (RLS stays off). Prefer declaring RLS in `db/rls.json` and letting `pxbaas app db-init` bind `table_schema` for you. See `references/multi-tenant-apps.md`.
169
+ - **On a multi-tenant profile, `db query` / `db push` / `app db-init` route through `/api/tenant-ddl` with the per-tenant service_role key** — DDL runs on the tenant's OWN db (GRANT-isolated) and RLS goes through the structured `/rls/*` endpoints (`table_schema` bound server-side). `/pg/query` stays platform-admin only and rejects per-tenant keys; do not hand-run central RLS INSERTs with a global key.
170
+ - **NEVER parse human-readable output** — always use `--json`.
171
+ - **NEVER loop-retry Zero capacity/rate errors** (`429 SUPABASE_LIMIT_REACHED` / `503 SUPABASE_POOL_EXHAUSTED`) — stop, inform the user, offer `pxbaas instance release`; retry at most once for pool exhaustion.
172
+ - **NEVER expect plaintext keys from `pxbaas provision`** — it stores them in the keyring and shows only fingerprints (this is why it is agent-runnable, unlike `pxbaas login`).
173
+ - **NEVER cat, echo, commit or transmit a tenant access bundle** (`*.pxbaas.env`) — it holds plaintext, ~10-year, non-revocable keys. The CLI only writes them to a `0600` file or the keyring; distributing the file is the operator's decision, made over a secure channel.
174
+ - **NEVER create a tenant as a workaround for a missing key.** Run `tenant ls` first: most "no key" cases are an existing tenant whose key was never handed over. A create that collides with a soft-deleted id resurrects it and regenerates that tenant's keys — the CLI refuses this without `--reactivate`.
175
+ - **NEVER upload frontend source, `.env` files, source maps, `node_modules`, Service Workers, or binary assets as a Webapp artifact.** Build first; upload only the bounded static output. Put large/binary assets on Storage/CDN (see app-deploy.md).
176
+
177
+ ## Global flags
178
+
179
+ `--json` (machine-readable output) · `--profile <name>` (select environment) · `--debug` (verbose) · `-V/--version`.
180
+
181
+ ## Installing / updating these skills
182
+
183
+ The CLI ships **two** bundled skills — `pxbaas-cli` (this one) and `pxbaas-app-spec` (webapp authoring) — installable into Agent hosts (offline, no login):
184
+ `pxbaas skill install --host <qoder|claude|cursor|qwen|hermes|codex|gemini|copilot|qwenworkcn|agents>` (or `--all`, which skips the neutral `agents` location) installs **all** bundled skills; `--skill <name>` installs just one. `--scope project` writes repository-level conventions instead (`.agents/skills`, `.gemini/skills`, `.github/skills`, `.claude/skills`, `.qwen/skills`, `.trae/skills`, `.codebuddy/skills`, `.cline/skills`), so skills travel with the code; with `--agents-md` it also maintains a managed pointer block in AGENTS.md for agents without a SKILL.md convention. Also `pxbaas skill list` and `pxbaas skill remove` (two-phase). These are setup/meta commands, not part of the data-plane surface above.
185
+
186
+ > The command surface above is derived from the actual source (`apps/baas/src`). When commands change, update this skill and the references accordingly.
@@ -0,0 +1,68 @@
1
+ # Live API Reference (`/docs`)
2
+
3
+ Every running BaaS instance serves an authoritative, **no-auth** API reference as inline Markdown:
4
+
5
+ ```
6
+ GET ${endpoint}/docs
7
+ ```
8
+
9
+ - `${endpoint}` is the profile's Kong base URL (e.g. `http://<baas-url>:8000`). Get it from `pxbaas status --json` (`.endpoint`) or `pxbaas whoami --json`.
10
+ - No authentication required; returns `text/markdown`, HTTP 200.
11
+ - It is **version-aligned with the deployed instance**, so it is the most accurate source for API details, multi-tenant behavior, and limitations.
12
+
13
+ ## When to fetch it
14
+
15
+ Fetch `${endpoint}/docs` (via WebFetch, or `curl -s ${endpoint}/docs`) when you need deeper detail than this skill provides, e.g.:
16
+ - exact endpoint semantics for a component (REST/Auth/Storage/Realtime/Functions/Meta)
17
+ - single-tenant vs multi-tenant request requirements and key hierarchy
18
+ - error-code meanings, rate-limit behavior, tenant status codes
19
+ - the full "Limitations vs Official Supabase" list before writing SQL or designing queries
20
+
21
+ How to fetch:
22
+ ```bash
23
+ curl -s "$(pxbaas status --json | sed -n 's/.*"endpoint": *"\([^"]*\)".*/\1/p')/docs"
24
+ # or simply: curl -s http://<baas-url>:8000/docs
25
+ ```
26
+
27
+ ## What `/docs` contains (content map)
28
+
29
+ | Section | Covers |
30
+ |---|---|
31
+ | Overview & Component Summary | Path prefixes for MysqlREST / Auth / Storage / Realtime / Functions / PG-Meta / Management API / Studio, all via Kong :8000 |
32
+ | Single-Tenant vs Multi-Tenant | `MULTI_TENANT_MODE`, `tenant_id` claim / `X-Tenant-Id`, per-tenant `jwt_secret`, 403/410 semantics, storage path rewriting, key hierarchy |
33
+ | Quick Start | Minimum headers (`apikey` + `Authorization: Bearer`), example requests |
34
+ | Authentication & Keys | `anon_key` vs `service_role_key`, JWT structure (HS256, `role`/`iss`/`iat`/`exp`) |
35
+ | REST API (MysqlREST) | CRUD, filtering, sorting, pagination, embedding, RPC; limitations |
36
+ | Auth (GoTrue) | Open vs authenticated endpoints; extra OAuth providers (alipay/aliyun/wechat/customdid) |
37
+ | Storage | Public vs authenticated endpoints, upload/download/move/copy/list, signed URLs |
38
+ | Realtime | WebSocket (Phoenix Channel), `postgres_changes` event name, polling-based CDC |
39
+ | Edge Functions | `/functions/v1/<name>`, per-function `verify_jwt`, invocation examples |
40
+ | Meta (PG-Meta `/pg/`) | **Admin only** — tables/columns/schemas/query/indexes; multi-tenant needs platform admin |
41
+ | Studio / Management API | **Admin only** — `/v1/projects/*`, function deploy |
42
+ | Limitations vs Official Supabase | Unavailable features + behavioral differences (critical, see below) |
43
+ | Health & Version Endpoints | No-auth health checks per service |
44
+ | Appendix | Error format, common error codes, tenant-id format, CORS, rate limiting, SDK compatibility |
45
+
46
+ ## Critical facts agents must not miss
47
+
48
+ **Backend is MySQL/PolarDB-X, not PostgreSQL.** Write MySQL dialect:
49
+
50
+ | Official Supabase (PostgreSQL) | PolarDB-X BaaS (MySQL) |
51
+ |---|---|
52
+ | `column::type` | `CAST(column AS type)` |
53
+ | `->`, `->>`, `@>` | `JSON_EXTRACT`, `JSON_UNQUOTE`, `JSON_CONTAINS` |
54
+ | `ILIKE` | `LIKE` (default collation is case-insensitive) |
55
+ | `gen_random_uuid()` | `UUID()` |
56
+ | `"col"` (double quotes) | `` `col` `` (backticks) |
57
+ | `schema.table` (same DB) | separate databases `` `db`.`table` `` |
58
+ | `auth.uid()` in RLS | `{{request.jwt.claim.sub}}` template var |
59
+
60
+ **Unavailable features** (do not attempt): GraphQL (`pg_graphql`), pgvector, PostGIS, pg_cron, materialized views, foreign tables, table inheritance, EXCLUDE constraints, partial indexes, `CREATE EXTENSION`, `CREATE PUBLICATION`.
61
+
62
+ **Other constraints:** resource embedding (FK joins) needs physical foreign keys — often unavailable on PolarDB-X sharded tables; DDL cannot run via REST (use `/pg/` or Studio) and implicitly commits; RLS is application-layer via `_mysqlrest_rls_policies`.
63
+
64
+ **Common error codes:** 401 `Unauthorized` / `token_expired`; 403 `Forbidden` / `tenant_suspended`; 404 `tenant_not_found`; 410 `tenant_deleted`; 400 invalid `tenant_id`.
65
+
66
+ ## Scope caveat (important)
67
+
68
+ `/docs` documents the **entire platform API**, including admin-only surfaces (PG-Meta `/pg/`, Management API `/v1/projects/*`) and tenant lifecycle. The **`pxbaas` CLI wraps only the customer data-plane subset** listed in the SKILL.md command map. Do not assume that because an endpoint appears in `/docs`, the CLI (or the current credential) can call it — admin APIs need platform-admin credentials the customer CLI does not use.
@@ -0,0 +1,186 @@
1
+ # Webapp Demo Deploy — `pxbaas app` commands
2
+
3
+ Covers: `app new` · `app capabilities` · `app deploy` · `app publish` · `app rollback` · `app unpublish` · `app destroy` · `app verify` · `app url` · `app list` · `app remove` · `app templates`.
4
+
5
+ `pxbaas app` supports both the legacy `spa`/`api`/`mpa` Edge Function demos and schemaVersion 2 Webapps with a prebuilt static frontend plus an optional Deno or Hono backend. Webapp deploys create immutable function candidates and publish them to a stable App mount using generation compare-and-swap (CAS).
6
+
7
+ > **How to WRITE the webapp code** (runtime contract, frontend/backend guardrails, templates, and deploy paths) lives in the dedicated **`pxbaas-app-spec` skill**. This page is only the `pxbaas app` command surface.
8
+
9
+ > **End-to-end workflow** (instance binding, scoped approvals, stage-by-stage recovery, network/whitelist handling) lives in **`pxbaas guide`**; run it first and follow it. This page covers only the `pxbaas app` command surface.
10
+
11
+ ## URL models
12
+
13
+ Legacy modes keep the Edge Function URL:
14
+
15
+ ```
16
+ {endpoint}/functions/v1/{slug}
17
+ ```
18
+
19
+ A schemaVersion 2 Webapp uses the platform-provided App origin and stable mount:
20
+
21
+ ```
22
+ {appEndpoint}/apps/{mount}/ # static frontend
23
+ {appEndpoint}/apps/{mount}/api/* # optional backend; prefix is stripped
24
+ ```
25
+
26
+ Never derive `appEndpoint`. Read it from `pxbaas app capabilities --json`. Output is `Public` only when `originMode=isolated`, `hostEnforced=true`, and `publicExposureAllowed=true`; otherwise treat the URL as `Preview`.
27
+
28
+ ## pxbaas app new — scaffold
29
+
30
+ ```bash
31
+ pxbaas app new <name> --template <spa|api|mpa|vanilla-static|react-vite|react-vite-hono|ssr-hono|ssr-auth|ssr-blog|csr-bff|ssr-shop|ssr-frameworks> [--dir ./apps] [--slug <slug>] [--force] [--json]
32
+ ```
33
+
34
+ - Legacy templates: `spa`, `api`, and `mpa`.
35
+ - Webapp templates: `vanilla-static`, `react-vite`, `react-vite-hono`, `ssr-hono`, `ssr-auth`, `ssr-blog`, `csr-bff`, `ssr-shop`, `ssr-frameworks`.
36
+ - Reference application templates (ship `db/schema.sql` + README + a DEPLOY CONFIG block to fill before deploy): `ssr-blog` (full-site SSR + proxy-injected session), `csr-bff` (front/back separated CSR + BFF), `ssr-shop` (React SSR shop, browser-side session), `ssr-frameworks` (four-framework SSR showcase).
37
+ - React templates pin React 18.3.1, React DOM 18.3.1, React Router DOM 6.28.0, and Vite 5.4.21, include a lockfile, use ordinary CSS, and route with `HashRouter`.
38
+ - Webapp scaffolds use nested `frontend/` and optional `backend/` directories plus a schemaVersion 2 `app.json`.
39
+ - Legacy slugs must match `^[a-zA-Z0-9][a-zA-Z0-9_-]*$` (≤128). Webapp candidate slugs are generated by the CLI.
40
+
41
+ ## pxbaas app capabilities — discover Webapp support
42
+
43
+ ```bash
44
+ pxbaas app capabilities --json
45
+ ```
46
+
47
+ Check this before building or deploying a schemaVersion 2 Webapp. The CLI blocks before upload unless schema version 2, `appEndpoint`, and public static delivery are enabled. A backend also requires native Deno; Hono additionally requires an exact `honoVersion` with offline readiness. The response also lists `ssrLibs` (the curated SSR renderers the instance pre-cached — the only `npm:` packages a worker may import besides Hono; an empty list means no SSR renderer imports are allowed) and the session contract (`sessionMode`/`sessionHeaders`).
48
+
49
+ ## pxbaas app deploy — upload and publish (destructive; confirm first)
50
+
51
+ ```bash
52
+ pxbaas app deploy <name> [--dir ./apps] [--slug <slug>] [--entrypoint index.ts] \
53
+ [--frontend <built-dir>] [--backend <source-dir>] [--backend-framework deno|hono] \
54
+ [--verify-jwt] [--dry-run] [--skip-spec-check] [--json]
55
+ ```
56
+
57
+ Legacy `spa`/`api`/`mpa` behavior is unchanged. For `mode=webapp`, deploy:
58
+
59
+ 1. reads and validates Manifest v2;
60
+ 2. checks capabilities before any upload;
61
+ 3. stages the prebuilt frontend from `<appDir>/<frontend.root>` (override the directory with `--frontend <dir>`), the optional backend, and the generated `app.json`;
62
+ 4. runs frontend/backend spec-lint and capability size limits;
63
+ 5. creates or loads the stable App mount;
64
+ 6. uploads an immutable `app_{appId}_r_{deployId}` candidate;
65
+ 7. publishes with `expectedGeneration` CAS and records the new generation locally.
66
+
67
+ For Hono, source must contain `npm:hono@{{HONO_VERSION}}`; deploy substitutes the exact capability version in the uploaded candidate. The local source keeps the placeholder. If publish fails, the candidate and current generation remain in local deployment state so `app publish` can retry safely.
68
+
69
+ All JSON failures use `{ "code": "...", "message": "..." }`. **Agents MUST NOT use `--skip-spec-check`** to force a bundled template or a failing artifact through — it bypasses the deployment/security contract. Only bypass when the user explicitly requests it, after you have listed every blocker and its impact.
70
+
71
+ **Legacy deploy output (`--json`)** includes the share URL, the preflight report, and the spec-lint result:
72
+ ```json
73
+ { "status": "deployed", "app": "shop", "slug": "shop", "verifyJwt": false,
74
+ "shareUrl": "http://pxsp-xxx:8000/functions/v1/shop",
75
+ "function": { "slug": "shop", "status": "ACTIVE", "version": 1, "verify_jwt": false },
76
+ "specLint": { "skipped": false, "passed": true, "blockers": [], "warnings": [ { "rule": "cors-options", "severity": "warning", "message": "...", "specRef": "pxbaas-app-spec/references/guardrails-pitfalls.md" } ] },
77
+ "preflight": { "quota": { "used": 2, "limit": 5, "ok": true }, "publicReachable": true, "warnings": ["verify_jwt=false: ..."] } }
78
+ ```
79
+ When the spec review fails, deploy exits non-zero with `status: "blocked"` and the list of blockers (each citing its `pxbaas-app-spec` reference).
80
+
81
+ ## Legacy preflight guardrails (run automatically before deploy)
82
+
83
+ | Check | Why | Effect |
84
+ |---|---|---|
85
+ | Function quota | each tenant defaults to `max_edge_functions=500` (429 over) | **blocker** when full; warning when near |
86
+ | Root-absolute refs | `/x` paths escape the `/functions/v1/` prefix onto Studio | warning: use relative paths / inline assets |
87
+ | Public reachability | sandbox URLs are internal; only `{public endpoint}/functions/v1/{slug}` is shareable | warning if endpoint is loopback/private |
88
+ | verify_jwt=false | the URL is public and the slug is enumerable | warning: never co-locate secrets |
89
+ | Entrypoint exists | deploy precondition | **blocker** if missing (`pxbaas app new` first) |
90
+ | Single-file size | worker memory ~150MB | warning if very large → suggest Storage/CDN |
91
+
92
+ **Quota stop-and-inform:** if the quota is full (or deploy returns 429), STOP — do not retry or work around. Tell the user, and offer `pxbaas app remove` / `pxbaas functions delete` to free a slot, or a platform-side quota increase. Let the user decide.
93
+
94
+ ## pxbaas app publish / rollback / unpublish
95
+
96
+ ```bash
97
+ pxbaas app publish <name> [--dir ./apps] [--json]
98
+ pxbaas app rollback <name> [--dir ./apps] [--json]
99
+ pxbaas app unpublish <name> [--dir ./apps] [--json]
100
+ ```
101
+
102
+ These commands are schemaVersion 2 only. They read `deployment.mountId`, `deployment.candidateFunctionSlug`, and `deployment.generation` from local `app.json`, send the generation as a CAS precondition, and persist the returned generation. A stale generation returns a normalized conflict code/message instead of silently overwriting another publish.
103
+
104
+ ## pxbaas app db-init — initialize the app's database (single- AND multi-tenant)
105
+
106
+ ```bash
107
+ pxbaas app db-init <name> [--dir ./apps] [--schema public] [--dry-run] [--yes] [--json]
108
+ ```
109
+
110
+ - Applies the app's bundled `db/schema.sql` (DDL + seed) plus the declarative `db/rls.json` (RLS registry). Shows the full plan and requires authorization (`--dry-run` previews; `--yes` for non-interactive); runs sequentially, **stops on the first error, never rolls back**. The CLI never auto-runs DDL during `deploy`.
111
+ - **Mode-aware:** single-tenant runs through `/pg/query` (`__SCHEMA__`→`--schema`, default `public`); multi-tenant runs through `/api/tenant-ddl` with the per-tenant service_role key (`__SCHEMA__` de-qualified, DDL on the tenant's own db, RLS via the structured `/rls/*` endpoints with `table_schema` bound server-side). See `references/multi-tenant-apps.md` §3b.
112
+ - **RLS source (hybrid):** `db/rls.json` is preferred; if absent, RLS INSERTs embedded in `schema.sql` are parsed (multi-tenant) or run verbatim (single-tenant). When both exist, `rls.json` wins and the embedded INSERTs are skipped with a warning.
113
+
114
+ ## pxbaas app destroy — permanently tear down a webapp (destructive; two-phase)
115
+
116
+ ```bash
117
+ pxbaas app destroy <name> [--dir ./apps] [--confirm] [--json]
118
+ ```
119
+
120
+ - schemaVersion 2 webapp only. Legacy `spa/api/mpa` functions keep using `app remove` (which now rejects a webapp and points here).
121
+ - **Reclaims two things**: the mount's edge-func candidates (`active`/`previous` plus any local unpublished `candidateFunctionSlug`) and the `_platform.app_mounts` mount-id record. Each function delete also revokes its share links and notifies the proxy (cache invalidation + quota release).
122
+ - **Does NOT drop DB business tables by default** (scope decision). Seed data and the central RLS metadata rows are left untouched. Pass `--purge-db` to also drop the app's own tables and remove its RLS registry rows (policies + the central `_mysqlrest_rls_tables` toggle, via `DELETE /api/tenant-ddl/rls/tables`), derived from `db/schema.sql` CREATE names + `db/rls.json`. On instances predating that DELETE endpoint the toggle row is left (harmless; re-created on the next `db-init`).
123
+ - Without `--confirm` it only previews what will be reclaimed (`status: "dry-run"`). With `--confirm` it destroys, then clears only the local `app.json` `deployment` block (source tree is kept for re-deploy).
124
+ - Idempotent: re-destroying an already-gone mount succeeds (`alreadyGone: true`). The server disables the mount before teardown, so a mid-way failure is safe to re-run.
125
+
126
+ ```json
127
+ { "status": "destroyed", "app": "shop", "mountId": "m-abc...", "alreadyGone": false,
128
+ "deletedFunctions": [ { "slug": "app_..._r_...", "deleted": true } ], "tablesUntouched": true }
129
+ ```
130
+
131
+ ## pxbaas app verify — cold-start-aware check
132
+
133
+ ```bash
134
+ pxbaas app verify <name> [--dir ./apps] [--slug <slug>] [--timeout 60] [--json]
135
+ ```
136
+
137
+ - Webapp mode resolves the stable mount, retries its frontend URL, and checks HTTP 200. It probes the backend only when `app.json` declares `backend.healthPath` (a mount-relative path such as `/api/health`); without it, verify does not require any fixed backend route.
138
+ - Legacy mode retries through sandbox cold start, checks HTTP 200 + content-type, and pings the built-in `?action=` API.
139
+ - Exits non-zero when verification fails.
140
+
141
+ ## pxbaas app url / list / remove / templates
142
+
143
+ ```bash
144
+ pxbaas app url <name> [--json] # print Public or Preview mount URL (legacy: share URL)
145
+ pxbaas app list [--json] # list deployed functions
146
+ pxbaas app remove <name> [--confirm] [--json] # delete a LEGACY spa/api/mpa function (two-phase; webapps use `app destroy`)
147
+ pxbaas app templates [--json] # list all bundled templates
148
+ ```
149
+
150
+ ## Delivering access — IP whitelist after publish / share
151
+
152
+ A published Webapp URL (`app url`) and any secure share link (`app share create`) are gated by the **instance IP whitelist**: a recipient whose egress IP is not allowed cannot open them, even though your machine can. So after `app deploy` / `app publish` / `app url` or `app share create`, **proactively raise the whitelist with the user** and act by instance kind:
153
+
154
+ - **Zero trial instance** (profile `source: zero`): the CLI can manage it. Preview, then append on approval (append-only and idempotent — never deletes existing entries, so it cannot lock you out):
155
+ ```bash
156
+ pxbaas instance whitelist get --json
157
+ pxbaas instance whitelist add <recipient-ip-or-cidr> --json
158
+ ```
159
+ The `add` call itself must originate from an already-allowed IP (claiming IP or an existing whitelist entry); otherwise it returns `IP_MISMATCH`. See `provision.md`.
160
+ - **Purchased / production instance**: `pxbaas instance whitelist` is **Zero-only** and will refuse on a `login` profile. Remind the user to add the recipient's egress IP via the cloud console / control plane **in time**, or the published/shared URL stays unreachable for them.
161
+
162
+ `Preview` exposure (shared origin, not an isolated public App domain) is a **separate** limitation from the IP whitelist — state both, and never promise public access from a local HTTP 200. Cross-ref: `pxbaas guide` step 8.
163
+
164
+ ## Constraints (state these to the user)
165
+
166
+ - A Webapp frontend must be prebuilt and prefix-safe: relative Vite base, `HashRouter`, no Service Worker, `.env`, source map, `node_modules`, source tree, or binary artifact.
167
+ - A first-release backend must call `Deno.serve`, avoid Node APIs and remote imports, declare no Secrets, and use `egressPolicy=deny`. Hono must match the exact capability version.
168
+ - Capabilities and artifact limits are authoritative per instance. Do not bypass an unsupported feature.
169
+ - Legacy Edge Function demos retain their cold-start and quota constraints. Put large/binary assets on Storage/CDN.
170
+ - Full limits and the code contract: see the **`pxbaas-app-spec` skill**.
171
+
172
+ ## Typical workflow
173
+
174
+ ```bash
175
+ pxbaas app capabilities --json
176
+ pxbaas app new shop --template react-vite-hono --json
177
+ (cd apps/shop/frontend && npm ci && npm run build)
178
+ pxbaas app deploy shop --frontend apps/shop/frontend/dist --backend apps/shop/backend --json
179
+ pxbaas app verify shop --json
180
+ pxbaas app url shop --json
181
+ # Later lifecycle operations use generation CAS:
182
+ pxbaas app rollback shop --json
183
+ pxbaas app unpublish shop --json
184
+ ```
185
+
186
+ > `pxbaas app` builds on `pxbaas functions` (see edge-functions.md) and needs an instance — provision one with `pxbaas provision` if you have none (see provision.md).
@@ -0,0 +1,116 @@
1
+ # Credentials, Environment & User Management
2
+
3
+ Covers: `login` (human-only) · `profile import` (agent-runnable, env-file) · `logout` · `whoami` · `status` · `doctor` · `profile` · `auth users` · `tenant login` / `tenant logout` (operator credentials; see tenant-admin.md).
4
+
5
+ ## login — agents must NEVER run this
6
+
7
+ ```bash
8
+ pxbaas login --endpoint <url> --tenant-id <id> --anon-key-stdin --service-key-stdin
9
+ ```
10
+
11
+ - **Requires an interactive TTY** (it prompts via inquirer); agents cannot complete it. **Do not attempt.**
12
+ - Keys are read from stdin via `--anon-key-stdin` / `--service-key-stdin` so they never land in shell history.
13
+ - Credentials are stored in the OS keyring (keytar), falling back to a `0600` file when no keyring is available.
14
+ - If another command reports `No active profile. Use "pxbaas login" ...` → **ask the user to log in manually**, OR — if a Supabase/BaaS `.env` file for the instance is available — bind it non-interactively with `pxbaas profile import <env-file>` (see below; that one IS agent-runnable).
15
+
16
+ ## profile import — bind an instance from a `.env` file (agents MAY run this)
17
+
18
+ ```bash
19
+ pxbaas profile import <env-file> --name <profile> [--intranet] --json
20
+ ```
21
+
22
+ - Reads `SUPABASE_URL` (fallback `SUPABASE_PUBLIC_URL` / `SUPABASE_INTRANET_URL`), `SUPABASE_ANON_KEY` (fallback `ANON_KEY` / `GLOBAL_ANON_KEY`) and `SUPABASE_SERVICE_ROLE_KEY` (fallback `SERVICE_ROLE_KEY` / `GLOBAL_SERVICE_ROLE_KEY`) from the file, validates the JWTs (rejects expired keys), then writes the profile + credentials and switches current to it.
23
+ - **Agent-runnable**: keys come from a file, never from argv/shell history, so no TTY is needed. Prefer this over `login` when you already have the instance `.env`.
24
+ - `--intranet` prefers `SUPABASE_INTRANET_URL` (VPC-internal entrypoint) over the public URL. `--name` sets the profile name (default: global `--profile`, else `default`); an existing profile of the same name is **overwritten**.
25
+ - **Multi-tenant env files are supported** when they carry tenant-level credentials: `MULTI_TENANT_MODE=true` + `DEFAULT_TENANT_ID` + `TENANT_ANON_KEY` + `TENANT_SERVICE_ROLE_KEY`. Global keys (`GLOBAL_ANON_KEY` / `GLOBAL_SERVICE_ROLE_KEY`) are reported as present-but-not-imported — they cannot reach tenant resources, so the profile never absorbs them.
26
+ - If a `MULTI_TENANT_MODE=true` file lacks the tenant keys, the command refuses and prints a diagnosis (which variables exist, whether each JWT carries a `tenant_id` claim) plus one of two routes: the operator path (`pxbaas tenant login` → `tenant ls` → `tenant keys <id> --as-profile`) or a checklist to send to the operator. Nothing is created and nothing is imported either way; the temporary admin probe it runs to pick the route does not persist the credentials it borrowed.
27
+ - **`DASHBOARD_USERNAME` / `DASHBOARD_PASSWORD` in an env file are NOT imported by default.** Only `--with-admin` binds them, and then only after the credentials actually open the tenant admin channel. Pass `--with-admin` only when the user is the instance operator.
28
+
29
+ ## Operator credentials (`tenant login`)
30
+
31
+ ```bash
32
+ pxbaas tenant login --endpoint https://<gateway> # TTY: masked password prompt
33
+ printf '%s\n%s\n' "$USER" "$PASS" | \
34
+ pxbaas tenant login --endpoint https://<gateway> --user-stdin --password-stdin
35
+ pxbaas tenant logout # drops dashboard creds only, keeps tenant keys
36
+ ```
37
+
38
+ - Stored under a separate keyring account (`admin/<profile>`); data-plane commands cannot read it.
39
+ - The password is refused in argv (`--dashboard-password` / `--admin-password` are blocked by the same guard as API keys).
40
+ - `tenant login` probes the admin channel **before** storing; a refused probe stores nothing.
41
+ - `pxbaas whoami --json` reports `platformAdmin: {available, userMasked, passwordFingerprint}` — never the secret.
42
+
43
+ ## Verify login state (run these first)
44
+
45
+ ```bash
46
+ pxbaas whoami --json # profile / endpoint / tenant / mode + key fingerprints (sha256 first 8 + last 4)
47
+ pxbaas status --json # capability URLs: real address of rest / auth / storage / functions / meta
48
+ pxbaas doctor --json # health checks: connectivity, JWT validity, expiry, tenant status
49
+ ```
50
+
51
+ `whoami --json` shape:
52
+ ```json
53
+ {
54
+ "profile": "local",
55
+ "endpoint": "http://<baas-url>:8000",
56
+ "tenantId": "tenant_a",
57
+ "mode": "multi-tenant",
58
+ "anonKey": { "fingerprint": "ab12cd34…wxyz", "role": "anon", "tenantId": "tenant_a", "expiry": "2026-12-31T23:59:59Z", "isExpired": false },
59
+ "serviceKey": { "fingerprint": "ef56gh78…wxyz", "role": "service_role", "tenantId": "tenant_a", "expiry": "2026-12-31T23:59:59Z", "isExpired": false },
60
+ "storedAt": "2026-09-15T10:00:00Z"
61
+ }
62
+ ```
63
+
64
+ `status --json` shape:
65
+ ```json
66
+ {
67
+ "profile": "local",
68
+ "endpoint": "http://<baas-url>:8000",
69
+ "tenantId": "tenant_a",
70
+ "mode": "multi-tenant",
71
+ "capabilities": {
72
+ "auth": "http://<baas-url>:8000/auth/v1",
73
+ "rest": "http://<baas-url>:8000/rest/v1",
74
+ "storage": "http://<baas-url>:8000/storage/v1",
75
+ "functions": "http://<baas-url>:8000/functions/v1",
76
+ "meta": "http://<baas-url>:8000/pg"
77
+ }
78
+ }
79
+ ```
80
+
81
+ - Output is **fingerprint-only**; you can never see a plaintext key. Do not expect or try to echo one.
82
+
83
+ ## logout
84
+
85
+ ```bash
86
+ pxbaas logout # clears credentials for the current profile
87
+ ```
88
+
89
+ ## profile — multi-environment management
90
+
91
+ ```bash
92
+ pxbaas profile ls --json # list all profiles
93
+ pxbaas profile use <name> --json # switch current profile
94
+ pxbaas profile rm <name> --json # remove a profile (destructive to local config — confirm first)
95
+ pxbaas profile import <env-file> --name <profile> --json # bind a single-tenant instance from a .env file (agent-runnable; see above)
96
+ ```
97
+
98
+ - You can also pass global `--profile <name>` to target one environment without changing the default.
99
+ - **Never mix credentials across profiles**: the CLI validates the key's `tenant_id` against the profile.
100
+
101
+ ## auth users — user management (requires service_role, bypasses RLS)
102
+
103
+ ```bash
104
+ pxbaas auth users list --page 1 --per-page 50 --json
105
+ pxbaas auth users get <userId> --json
106
+ pxbaas auth users create --email <email> --password <pwd> [--confirm-email] --json # write
107
+ pxbaas auth users delete <userId> --json # destructive
108
+ pxbaas auth users invite <email> --json # write (sends invite email)
109
+ ```
110
+
111
+ - `--email` and `--password` are required for `create`; `--confirm-email` defaults to true (auto-confirm the email).
112
+ - These hit the GoTrue admin API (`/auth/v1/admin/users`) and need `service_role`.
113
+ - **write/destructive**: confirm with the user before `create` / `delete` / `invite` (see safety-and-two-phase.md).
114
+ - `delete <userId>` is irreversible — run `get <userId>` first to verify identity.
115
+
116
+ > Underlying API details (Auth endpoints, multi-tenant key rules): fetch `${endpoint}/docs` — see api-reference.md.