primitive-admin 1.2.0-alpha.1 → 1.2.0-alpha.11

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 (410) hide show
  1. package/README.md +105 -134
  2. package/assets/skill/skills/primitive-platform/SKILL.md +37 -4
  3. package/dist/bin/primitive.js +30 -35
  4. package/dist/bin/primitive.js.map +1 -1
  5. package/dist/src/commands/agent-sessions.d.ts +133 -0
  6. package/dist/src/commands/agent-sessions.js +792 -0
  7. package/dist/src/commands/agent-sessions.js.map +1 -0
  8. package/dist/src/commands/analytics.js +0 -148
  9. package/dist/src/commands/analytics.js.map +1 -1
  10. package/dist/src/commands/apps-children.d.ts +54 -0
  11. package/dist/src/commands/apps-children.js +631 -0
  12. package/dist/src/commands/apps-children.js.map +1 -0
  13. package/dist/src/commands/apps.d.ts +6 -0
  14. package/dist/src/commands/apps.js +131 -9
  15. package/dist/src/commands/apps.js.map +1 -1
  16. package/dist/src/commands/auth-sessions.d.ts +3 -3
  17. package/dist/src/commands/auth-sessions.js +117 -23
  18. package/dist/src/commands/auth-sessions.js.map +1 -1
  19. package/dist/src/commands/auth.js +460 -36
  20. package/dist/src/commands/auth.js.map +1 -1
  21. package/dist/src/commands/collections.js +316 -256
  22. package/dist/src/commands/collections.js.map +1 -1
  23. package/dist/src/commands/config.d.ts +1 -1
  24. package/dist/src/commands/config.js +60 -28
  25. package/dist/src/commands/config.js.map +1 -1
  26. package/dist/src/commands/connections.js +11 -12
  27. package/dist/src/commands/connections.js.map +1 -1
  28. package/dist/src/commands/database-type-configs.js +2 -76
  29. package/dist/src/commands/database-type-configs.js.map +1 -1
  30. package/dist/src/commands/databases.d.ts +9 -0
  31. package/dist/src/commands/databases.js +221 -457
  32. package/dist/src/commands/databases.js.map +1 -1
  33. package/dist/src/commands/db3-types.d.ts +15 -0
  34. package/dist/src/commands/db3-types.js +157 -0
  35. package/dist/src/commands/db3-types.js.map +1 -0
  36. package/dist/src/commands/db3.d.ts +12 -0
  37. package/dist/src/commands/db3.js +1052 -0
  38. package/dist/src/commands/db3.js.map +1 -0
  39. package/dist/src/commands/documents.d.ts +121 -2
  40. package/dist/src/commands/documents.js +1601 -1251
  41. package/dist/src/commands/documents.js.map +1 -1
  42. package/dist/src/commands/env.d.ts +9 -1
  43. package/dist/src/commands/env.js +164 -49
  44. package/dist/src/commands/env.js.map +1 -1
  45. package/dist/src/commands/function-trigger-commands.d.ts +28 -0
  46. package/dist/src/commands/function-trigger-commands.js +341 -0
  47. package/dist/src/commands/function-trigger-commands.js.map +1 -0
  48. package/dist/src/commands/functions.js +297 -24
  49. package/dist/src/commands/functions.js.map +1 -1
  50. package/dist/src/commands/groups.js +150 -49
  51. package/dist/src/commands/groups.js.map +1 -1
  52. package/dist/src/commands/guides.js +5 -5
  53. package/dist/src/commands/init.d.ts +7 -0
  54. package/dist/src/commands/init.js +23 -5
  55. package/dist/src/commands/init.js.map +1 -1
  56. package/dist/src/commands/integrations.js +14 -8
  57. package/dist/src/commands/integrations.js.map +1 -1
  58. package/dist/src/commands/metadata-category-configs.d.ts +2 -2
  59. package/dist/src/commands/metadata-category-configs.js +2 -2
  60. package/dist/src/commands/prompts.d.ts +7 -0
  61. package/dist/src/commands/prompts.js +48 -5
  62. package/dist/src/commands/prompts.js.map +1 -1
  63. package/dist/src/commands/scripts.d.ts +9 -17
  64. package/dist/src/commands/scripts.js +24 -479
  65. package/dist/src/commands/scripts.js.map +1 -1
  66. package/dist/src/commands/sync-app-settings.d.ts +36 -8
  67. package/dist/src/commands/sync-app-settings.js +109 -23
  68. package/dist/src/commands/sync-app-settings.js.map +1 -1
  69. package/dist/src/commands/sync.d.ts +360 -610
  70. package/dist/src/commands/sync.js +3151 -6697
  71. package/dist/src/commands/sync.js.map +1 -1
  72. package/dist/src/commands/tokens.js +3 -3
  73. package/dist/src/commands/tokens.js.map +1 -1
  74. package/dist/src/commands/users.js +77 -2
  75. package/dist/src/commands/users.js.map +1 -1
  76. package/dist/src/commands/workflows.d.ts +5 -83
  77. package/dist/src/commands/workflows.js +57 -2282
  78. package/dist/src/commands/workflows.js.map +1 -1
  79. package/dist/src/lib/aggregate-output.d.ts +25 -0
  80. package/dist/src/lib/aggregate-output.js +53 -0
  81. package/dist/src/lib/aggregate-output.js.map +1 -0
  82. package/dist/src/lib/api-client.d.ts +681 -551
  83. package/dist/src/lib/api-client.js +880 -814
  84. package/dist/src/lib/api-client.js.map +1 -1
  85. package/dist/src/lib/app-settings-descriptor.d.ts +47 -1
  86. package/dist/src/lib/app-settings-descriptor.js +114 -10
  87. package/dist/src/lib/app-settings-descriptor.js.map +1 -1
  88. package/dist/src/lib/auth-fixtures.d.ts +44 -0
  89. package/dist/src/lib/auth-fixtures.js +61 -0
  90. package/dist/src/lib/auth-fixtures.js.map +1 -0
  91. package/dist/src/lib/auth-flow.d.ts +41 -1
  92. package/dist/src/lib/auth-flow.js +70 -16
  93. package/dist/src/lib/auth-flow.js.map +1 -1
  94. package/dist/src/lib/block-layout.d.ts +12 -23
  95. package/dist/src/lib/block-layout.js +26 -92
  96. package/dist/src/lib/block-layout.js.map +1 -1
  97. package/dist/src/lib/block-selector.d.ts +2 -2
  98. package/dist/src/lib/block-selector.js +2 -2
  99. package/dist/src/lib/child-apps-local.d.ts +164 -0
  100. package/dist/src/lib/child-apps-local.js +258 -0
  101. package/dist/src/lib/child-apps-local.js.map +1 -0
  102. package/dist/src/lib/ci-session-request.d.ts +22 -0
  103. package/dist/src/lib/ci-session-request.js +51 -0
  104. package/dist/src/lib/ci-session-request.js.map +1 -0
  105. package/dist/src/lib/codegen-shared/generatedFiles.d.ts +10 -8
  106. package/dist/src/lib/codegen-shared/generatedFiles.js +21 -15
  107. package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -1
  108. package/dist/src/lib/codegen-shared/prettierStable.d.ts +1 -1
  109. package/dist/src/lib/codegen-shared/prettierStable.js +1 -1
  110. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +2 -2
  111. package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +2 -2
  112. package/dist/src/lib/collection-export.d.ts +76 -15
  113. package/dist/src/lib/collection-export.js +116 -23
  114. package/dist/src/lib/collection-export.js.map +1 -1
  115. package/dist/src/lib/collection-principal.d.ts +22 -0
  116. package/dist/src/lib/collection-principal.js +35 -0
  117. package/dist/src/lib/collection-principal.js.map +1 -0
  118. package/dist/src/lib/config-object-descriptor.d.ts +3 -22
  119. package/dist/src/lib/config-object-descriptor.js +56 -290
  120. package/dist/src/lib/config-object-descriptor.js.map +1 -1
  121. package/dist/src/lib/config-payload.js +2 -3
  122. package/dist/src/lib/config-payload.js.map +1 -1
  123. package/dist/src/lib/config-surface.d.ts +5 -7
  124. package/dist/src/lib/config-surface.js +18 -40
  125. package/dist/src/lib/config-surface.js.map +1 -1
  126. package/dist/src/lib/connections-list.d.ts +10 -0
  127. package/dist/src/lib/connections-list.js +18 -0
  128. package/dist/src/lib/connections-list.js.map +1 -0
  129. package/dist/src/lib/credentials-home.d.ts +58 -0
  130. package/dist/src/lib/credentials-home.js +204 -0
  131. package/dist/src/lib/credentials-home.js.map +1 -0
  132. package/dist/src/lib/credentials-lock.d.ts +88 -0
  133. package/dist/src/lib/credentials-lock.js +302 -0
  134. package/dist/src/lib/credentials-lock.js.map +1 -0
  135. package/dist/src/lib/credentials-store.d.ts +179 -24
  136. package/dist/src/lib/credentials-store.js +712 -77
  137. package/dist/src/lib/credentials-store.js.map +1 -1
  138. package/dist/src/lib/csv.d.ts +8 -9
  139. package/dist/src/lib/csv.js +3 -4
  140. package/dist/src/lib/csv.js.map +1 -1
  141. package/dist/src/lib/custodian.d.ts +8 -0
  142. package/dist/src/lib/custodian.js +18 -0
  143. package/dist/src/lib/custodian.js.map +1 -0
  144. package/dist/src/lib/db-codegen/dbGenerator.js +5 -16
  145. package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -1
  146. package/dist/src/lib/db-codegen/dbNaming.d.ts +5 -13
  147. package/dist/src/lib/db-codegen/dbNaming.js +5 -17
  148. package/dist/src/lib/db-codegen/dbNaming.js.map +1 -1
  149. package/dist/src/lib/db-codegen/dbTemplates.d.ts +7 -56
  150. package/dist/src/lib/db-codegen/dbTemplates.js +25 -125
  151. package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -1
  152. package/dist/src/lib/db-codegen/dbTsTypes.d.ts +2 -2
  153. package/dist/src/lib/db-codegen/dbTsTypes.js +2 -2
  154. package/dist/src/lib/db-codegen/dbTypeIR.d.ts +67 -2
  155. package/dist/src/lib/db-codegen/dbTypeIR.js +13 -2
  156. package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
  157. package/dist/src/lib/db3-export.d.ts +231 -0
  158. package/dist/src/lib/db3-export.js +510 -0
  159. package/dist/src/lib/db3-export.js.map +1 -0
  160. package/dist/src/lib/db3-index-output.d.ts +27 -0
  161. package/dist/src/lib/db3-index-output.js +49 -0
  162. package/dist/src/lib/db3-index-output.js.map +1 -0
  163. package/dist/src/lib/document-export-lookups.d.ts +31 -0
  164. package/dist/src/lib/document-export-lookups.js +53 -0
  165. package/dist/src/lib/document-export-lookups.js.map +1 -0
  166. package/dist/src/lib/document-export-permissions.d.ts +7 -5
  167. package/dist/src/lib/document-export-permissions.js +7 -5
  168. package/dist/src/lib/document-export-permissions.js.map +1 -1
  169. package/dist/src/lib/document-export-record-log.d.ts +57 -0
  170. package/dist/src/lib/document-export-record-log.js +215 -0
  171. package/dist/src/lib/document-export-record-log.js.map +1 -0
  172. package/dist/src/lib/document-ingest-artifact.d.ts +26 -2
  173. package/dist/src/lib/document-ingest-artifact.js +42 -8
  174. package/dist/src/lib/document-ingest-artifact.js.map +1 -1
  175. package/dist/src/lib/document-ingest-format2.d.ts +36 -0
  176. package/dist/src/lib/document-ingest-format2.js +78 -0
  177. package/dist/src/lib/document-ingest-format2.js.map +1 -0
  178. package/dist/src/lib/document-ingest-input.d.ts +9 -0
  179. package/dist/src/lib/document-ingest-input.js +28 -1
  180. package/dist/src/lib/document-ingest-input.js.map +1 -1
  181. package/dist/src/lib/document-ingest-rows.d.ts +16 -0
  182. package/dist/src/lib/document-ingest-rows.js +17 -0
  183. package/dist/src/lib/document-ingest-rows.js.map +1 -1
  184. package/dist/src/lib/document-ingest.d.ts +33 -1
  185. package/dist/src/lib/document-ingest.js +49 -0
  186. package/dist/src/lib/document-ingest.js.map +1 -1
  187. package/dist/src/lib/document-schema-rows.d.ts +42 -0
  188. package/dist/src/lib/document-schema-rows.js +53 -0
  189. package/dist/src/lib/document-schema-rows.js.map +1 -0
  190. package/dist/src/lib/env-resolver-core.d.ts +70 -2
  191. package/dist/src/lib/env-resolver-core.js +137 -20
  192. package/dist/src/lib/env-resolver-core.js.map +1 -1
  193. package/dist/src/lib/env-resolver.d.ts +14 -2
  194. package/dist/src/lib/env-resolver.js +32 -10
  195. package/dist/src/lib/env-resolver.js.map +1 -1
  196. package/dist/src/lib/function-authorize-check.d.ts +142 -0
  197. package/dist/src/lib/function-authorize-check.js +310 -0
  198. package/dist/src/lib/function-authorize-check.js.map +1 -0
  199. package/dist/src/lib/function-authorize-view.d.ts +15 -0
  200. package/dist/src/lib/function-authorize-view.js +50 -0
  201. package/dist/src/lib/function-authorize-view.js.map +1 -0
  202. package/dist/src/lib/function-bundle.d.ts +38 -18
  203. package/dist/src/lib/function-bundle.js +96 -35
  204. package/dist/src/lib/function-bundle.js.map +1 -1
  205. package/dist/src/lib/function-collect.d.ts +75 -12
  206. package/dist/src/lib/function-collect.js +427 -12
  207. package/dist/src/lib/function-collect.js.map +1 -1
  208. package/dist/src/lib/function-db-types.d.ts +29 -0
  209. package/dist/src/lib/function-db-types.js +117 -7
  210. package/dist/src/lib/function-db-types.js.map +1 -1
  211. package/dist/src/lib/function-document-types.d.ts +5 -3
  212. package/dist/src/lib/function-document-types.js +10 -14
  213. package/dist/src/lib/function-document-types.js.map +1 -1
  214. package/dist/src/lib/function-lint.d.ts +34 -0
  215. package/dist/src/lib/function-lint.js +112 -0
  216. package/dist/src/lib/function-lint.js.map +1 -0
  217. package/dist/src/lib/function-log-row.js +21 -2
  218. package/dist/src/lib/function-log-row.js.map +1 -1
  219. package/dist/src/lib/function-run.d.ts +16 -21
  220. package/dist/src/lib/function-run.js +37 -30
  221. package/dist/src/lib/function-run.js.map +1 -1
  222. package/dist/src/lib/function-schema-codegen.d.ts +1 -1
  223. package/dist/src/lib/function-schema-codegen.js +5 -5
  224. package/dist/src/lib/function-schema-codegen.js.map +1 -1
  225. package/dist/src/lib/function-source-roots.d.ts +67 -0
  226. package/dist/src/lib/function-source-roots.js +148 -0
  227. package/dist/src/lib/function-source-roots.js.map +1 -0
  228. package/dist/src/lib/function-sync.d.ts +108 -22
  229. package/dist/src/lib/function-sync.js +127 -39
  230. package/dist/src/lib/function-sync.js.map +1 -1
  231. package/dist/src/lib/function-trigger-listing.d.ts +11 -6
  232. package/dist/src/lib/function-trigger-listing.js +32 -11
  233. package/dist/src/lib/function-trigger-listing.js.map +1 -1
  234. package/dist/src/lib/function-typecheck.d.ts +37 -2
  235. package/dist/src/lib/function-typecheck.js +210 -28
  236. package/dist/src/lib/function-typecheck.js.map +1 -1
  237. package/dist/src/lib/function-versions.d.ts +2 -0
  238. package/dist/src/lib/function-versions.js +1 -0
  239. package/dist/src/lib/function-versions.js.map +1 -1
  240. package/dist/src/lib/generated-allowlist.js +0 -20
  241. package/dist/src/lib/generated-allowlist.js.map +1 -1
  242. package/dist/src/lib/generated-config-surfaces.d.ts +703 -203
  243. package/dist/src/lib/generated-config-surfaces.js +2270 -2014
  244. package/dist/src/lib/generated-config-surfaces.js.map +1 -1
  245. package/dist/src/lib/generated-sdk-types.d.ts +1 -1
  246. package/dist/src/lib/generated-sdk-types.js +1 -1
  247. package/dist/src/lib/generated-sdk-types.js.map +1 -1
  248. package/dist/src/lib/init-adopt.js +12 -3
  249. package/dist/src/lib/init-adopt.js.map +1 -1
  250. package/dist/src/lib/init-login-note.d.ts +13 -0
  251. package/dist/src/lib/init-login-note.js +22 -0
  252. package/dist/src/lib/init-login-note.js.map +1 -0
  253. package/dist/src/lib/json-value.d.ts +6 -0
  254. package/dist/src/lib/json-value.js +13 -0
  255. package/dist/src/lib/json-value.js.map +1 -0
  256. package/dist/src/lib/load-routes.d.ts +33 -0
  257. package/dist/src/lib/load-routes.js +35 -0
  258. package/dist/src/lib/load-routes.js.map +1 -0
  259. package/dist/src/lib/local-state.d.ts +38 -7
  260. package/dist/src/lib/local-state.js +172 -49
  261. package/dist/src/lib/local-state.js.map +1 -1
  262. package/dist/src/lib/local-test-cases.d.ts +5 -2
  263. package/dist/src/lib/local-test-cases.js +7 -4
  264. package/dist/src/lib/local-test-cases.js.map +1 -1
  265. package/dist/src/lib/log-inspection.d.ts +42 -4
  266. package/dist/src/lib/log-inspection.js +37 -5
  267. package/dist/src/lib/log-inspection.js.map +1 -1
  268. package/dist/src/lib/login-exchange-check.d.ts +18 -0
  269. package/dist/src/lib/login-exchange-check.js +27 -0
  270. package/dist/src/lib/login-exchange-check.js.map +1 -0
  271. package/dist/src/lib/login-scope-lines.d.ts +25 -0
  272. package/dist/src/lib/login-scope-lines.js +45 -0
  273. package/dist/src/lib/login-scope-lines.js.map +1 -0
  274. package/dist/src/lib/logout-admin-session.d.ts +2 -1
  275. package/dist/src/lib/logout-admin-session.js +7 -1
  276. package/dist/src/lib/logout-admin-session.js.map +1 -1
  277. package/dist/src/lib/object-status-filter.d.ts +9 -1
  278. package/dist/src/lib/object-status-filter.js +9 -1
  279. package/dist/src/lib/object-status-filter.js.map +1 -1
  280. package/dist/src/lib/output.js +2 -0
  281. package/dist/src/lib/output.js.map +1 -1
  282. package/dist/src/lib/paginate.d.ts +0 -5
  283. package/dist/src/lib/paginate.js +0 -5
  284. package/dist/src/lib/paginate.js.map +1 -1
  285. package/dist/src/lib/pin-refusal-hint.d.ts +12 -0
  286. package/dist/src/lib/pin-refusal-hint.js +35 -0
  287. package/dist/src/lib/pin-refusal-hint.js.map +1 -0
  288. package/dist/src/lib/primitive-env-plugin.d.ts +99 -0
  289. package/dist/src/lib/primitive-env-plugin.js +408 -0
  290. package/dist/src/lib/primitive-env-plugin.js.map +1 -0
  291. package/dist/src/lib/project-config.d.ts +7 -0
  292. package/dist/src/lib/project-config.js +22 -1
  293. package/dist/src/lib/project-config.js.map +1 -1
  294. package/dist/src/lib/project-login-apps.d.ts +8 -0
  295. package/dist/src/lib/project-login-apps.js +27 -0
  296. package/dist/src/lib/project-login-apps.js.map +1 -0
  297. package/dist/src/lib/prompt-schema-codegen.d.ts +10 -3
  298. package/dist/src/lib/prompt-schema-codegen.js +52 -11
  299. package/dist/src/lib/prompt-schema-codegen.js.map +1 -1
  300. package/dist/src/lib/pull-write.d.ts +31 -0
  301. package/dist/src/lib/pull-write.js +49 -0
  302. package/dist/src/lib/pull-write.js.map +1 -0
  303. package/dist/src/lib/push-failure-report.d.ts +45 -0
  304. package/dist/src/lib/push-failure-report.js +57 -0
  305. package/dist/src/lib/push-failure-report.js.map +1 -0
  306. package/dist/src/lib/records-verbs.d.ts +69 -0
  307. package/dist/src/lib/records-verbs.js +40 -0
  308. package/dist/src/lib/records-verbs.js.map +1 -0
  309. package/dist/src/lib/refresh-admin-credentials.d.ts +7 -0
  310. package/dist/src/lib/refresh-admin-credentials.js +16 -4
  311. package/dist/src/lib/refresh-admin-credentials.js.map +1 -1
  312. package/dist/src/lib/root-import-decision.d.ts +65 -0
  313. package/dist/src/lib/root-import-decision.js +109 -0
  314. package/dist/src/lib/root-import-decision.js.map +1 -0
  315. package/dist/src/lib/run-status.d.ts +1 -1
  316. package/dist/src/lib/run-status.generated.d.ts +2 -2
  317. package/dist/src/lib/run-status.generated.js +3 -1
  318. package/dist/src/lib/run-status.generated.js.map +1 -1
  319. package/dist/src/lib/run-status.js +1 -1
  320. package/dist/src/lib/schema-codegen/generated-schema-descriptor.d.ts +129 -0
  321. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js +269 -0
  322. package/dist/src/lib/schema-codegen/generated-schema-descriptor.js.map +1 -0
  323. package/dist/src/lib/schema-codegen/naming.d.ts +35 -0
  324. package/dist/src/lib/schema-codegen/naming.js +83 -0
  325. package/dist/src/lib/schema-codegen/naming.js.map +1 -0
  326. package/dist/src/lib/schema-codegen/schemaToTs.d.ts +82 -0
  327. package/dist/src/lib/schema-codegen/schemaToTs.js +305 -0
  328. package/dist/src/lib/schema-codegen/schemaToTs.js.map +1 -0
  329. package/dist/src/lib/scope-request.d.ts +84 -0
  330. package/dist/src/lib/scope-request.js +235 -0
  331. package/dist/src/lib/scope-request.js.map +1 -0
  332. package/dist/src/lib/session-id.d.ts +9 -0
  333. package/dist/src/lib/session-id.js +28 -0
  334. package/dist/src/lib/session-id.js.map +1 -0
  335. package/dist/src/lib/snapshot-build-rows.d.ts +21 -0
  336. package/dist/src/lib/snapshot-build-rows.js +22 -0
  337. package/dist/src/lib/snapshot-build-rows.js.map +1 -1
  338. package/dist/src/lib/snapshot-build.js +8 -3
  339. package/dist/src/lib/snapshot-build.js.map +1 -1
  340. package/dist/src/lib/snapshots.d.ts +17 -1
  341. package/dist/src/lib/snapshots.js +50 -2
  342. package/dist/src/lib/snapshots.js.map +1 -1
  343. package/dist/src/lib/swift-codegen/agentGenerator.d.ts +6 -2
  344. package/dist/src/lib/swift-codegen/agentGenerator.js +57 -5
  345. package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -1
  346. package/dist/src/lib/swift-codegen/banners.d.ts +34 -7
  347. package/dist/src/lib/swift-codegen/banners.js +37 -7
  348. package/dist/src/lib/swift-codegen/banners.js.map +1 -1
  349. package/dist/src/lib/swift-codegen/dbGenerator.d.ts +4 -3
  350. package/dist/src/lib/swift-codegen/dbGenerator.js +14 -117
  351. package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
  352. package/dist/src/lib/swift-codegen/functionGenerator.d.ts +3 -3
  353. package/dist/src/lib/swift-codegen/functionGenerator.js +23 -18
  354. package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -1
  355. package/dist/src/lib/swift-codegen/generator.d.ts +5 -5
  356. package/dist/src/lib/swift-codegen/generator.js +35 -40
  357. package/dist/src/lib/swift-codegen/generator.js.map +1 -1
  358. package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +3 -3
  359. package/dist/src/lib/swift-codegen/schemaToSwift.js +4 -4
  360. package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
  361. package/dist/src/lib/swift-codegen/swiftKeys.d.ts +19 -0
  362. package/dist/src/lib/swift-codegen/swiftKeys.js +31 -0
  363. package/dist/src/lib/swift-codegen/swiftKeys.js.map +1 -0
  364. package/dist/src/lib/sync-paths.d.ts +35 -0
  365. package/dist/src/lib/sync-paths.js +57 -5
  366. package/dist/src/lib/sync-paths.js.map +1 -1
  367. package/dist/src/lib/sync-resource-types.d.ts +26 -26
  368. package/dist/src/lib/sync-resource-types.js +61 -189
  369. package/dist/src/lib/sync-resource-types.js.map +1 -1
  370. package/dist/src/lib/sync-selectors.d.ts +5 -1
  371. package/dist/src/lib/sync-selectors.js +23 -13
  372. package/dist/src/lib/sync-selectors.js.map +1 -1
  373. package/dist/src/lib/test-case-file-names.d.ts +3 -5
  374. package/dist/src/lib/test-case-file-names.js +3 -5
  375. package/dist/src/lib/test-case-file-names.js.map +1 -1
  376. package/dist/src/lib/toml-database-config.d.ts +15 -75
  377. package/dist/src/lib/toml-database-config.js +17 -306
  378. package/dist/src/lib/toml-database-config.js.map +1 -1
  379. package/dist/src/lib/transient-retry.d.ts +43 -0
  380. package/dist/src/lib/transient-retry.js +94 -0
  381. package/dist/src/lib/transient-retry.js.map +1 -0
  382. package/dist/src/lib/vars-override.d.ts +105 -0
  383. package/dist/src/lib/vars-override.js +143 -0
  384. package/dist/src/lib/vars-override.js.map +1 -0
  385. package/dist/src/lib/webhook-capture.d.ts +43 -0
  386. package/dist/src/lib/webhook-capture.js +91 -0
  387. package/dist/src/lib/webhook-capture.js.map +1 -0
  388. package/dist/src/lib/webhook-deliver.d.ts +18 -20
  389. package/dist/src/lib/webhook-deliver.js +34 -89
  390. package/dist/src/lib/webhook-deliver.js.map +1 -1
  391. package/dist/src/lib/webhook-test-run.d.ts +32 -0
  392. package/dist/src/lib/webhook-test-run.js +108 -0
  393. package/dist/src/lib/webhook-test-run.js.map +1 -0
  394. package/dist/src/lib/workflow-codegen/generator.d.ts +7 -7
  395. package/dist/src/lib/workflow-codegen/generator.js +16 -23
  396. package/dist/src/lib/workflow-codegen/generator.js.map +1 -1
  397. package/dist/src/lib/workflow-codegen/invokerIR.d.ts +6 -12
  398. package/dist/src/lib/workflow-codegen/invokerIR.js +4 -5
  399. package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -1
  400. package/dist/src/lib/workflow-toml-validator.d.ts +2 -0
  401. package/dist/src/lib/workflow-toml-validator.js +28 -1
  402. package/dist/src/lib/workflow-toml-validator.js.map +1 -1
  403. package/dist/src/types/index.d.ts +30 -37
  404. package/dist/src/validators.d.ts +7 -55
  405. package/dist/src/validators.js +7 -53
  406. package/dist/src/validators.js.map +1 -1
  407. package/dist/src/vite.d.ts +17 -0
  408. package/dist/src/vite.js +18 -0
  409. package/dist/src/vite.js.map +1 -0
  410. package/package.json +20 -12
@@ -1,10 +1,19 @@
1
- import { loadCredentials, saveCredentials, clearCredentials, isTokenExpired, getCurrentApp, getConfiguredServerUrl, } from "../lib/config.js";
2
- import { allowGlobalCredentials } from "../lib/credentials-store.js";
1
+ import { loadCredentials, saveCredentials, clearCredentials, isTokenExpired, getConfiguredServerUrl, } from "../lib/config.js";
2
+ import { allowGlobalCredentials, allowGlobalCredentialsForServer, clearLeftoverLogins, environmentToken, getCredentialsFilePath, globalLoginCommand, isProjectMode, leftoverLogins, loginEnvironments, mismatchedLogin, partitionFromEnvironment, sameServer, worktreeLoginNotes, } from "../lib/credentials-store.js";
3
+ import { PrimitiveEnvError } from "../lib/env-resolver-core.js";
4
+ import { isCiToken } from "../lib/session-id.js";
3
5
  import { browserLogin } from "../lib/auth-flow.js";
6
+ import { getCurrentEnvironment, getProjectConfig, requireCurrentEnvironment, } from "../lib/env-resolver.js";
7
+ import { buildScopeRequest } from "../lib/scope-request.js";
8
+ import { projectLoginApps } from "../lib/project-login-apps.js";
9
+ import { loginExchangeRefusal } from "../lib/login-exchange-check.js";
10
+ import { ApiClient, ApiError } from "../lib/api-client.js";
4
11
  import { fetchWithTLS } from "../lib/fetch.js";
5
12
  import { REFRESH_EXPIRED_MESSAGE, RefreshError, refreshAdminCredentials, } from "../lib/refresh-admin-credentials.js";
6
13
  import { logoutAdminSession } from "../lib/logout-admin-session.js";
14
+ import { loginScopeLines } from "../lib/login-scope-lines.js";
7
15
  import { registerAuthSessionsCommands } from "./auth-sessions.js";
16
+ import { outsideProjectServer } from "./apps.js";
8
17
  import { success, error, info, keyValue, json } from "../lib/output.js";
9
18
  function parseJwt(token) {
10
19
  try {
@@ -19,6 +28,120 @@ function parseJwt(token) {
19
28
  return {};
20
29
  }
21
30
  }
31
+ /**
32
+ * Whether a project is in scope. A project config that cannot be read counts
33
+ * as one, so the command reports it exactly as it always has.
34
+ */
35
+ function inProject() {
36
+ try {
37
+ return isProjectMode();
38
+ }
39
+ catch {
40
+ return true;
41
+ }
42
+ }
43
+ /** The environment's app, or undefined outside a project. */
44
+ function environmentAppId() {
45
+ try {
46
+ return getCurrentEnvironment()?.config.appId;
47
+ }
48
+ catch {
49
+ return undefined;
50
+ }
51
+ }
52
+ /**
53
+ * The project a login runs in: its server and the apps of the committed
54
+ * environments on it (#4512). Undefined outside a project.
55
+ */
56
+ function loginProject(serverUrl) {
57
+ const config = getProjectConfig();
58
+ return config ? { serverUrl, apps: projectLoginApps(config.environments, serverUrl) } : undefined;
59
+ }
60
+ /** The project a login's lines name (#4512); empty outside a project. */
61
+ function loginLinesContext(serverUrl) {
62
+ const config = getProjectConfig();
63
+ if (!config)
64
+ return {};
65
+ let signedIn = [];
66
+ try {
67
+ signedIn = loginEnvironments()?.environments ?? [];
68
+ }
69
+ catch {
70
+ // The environments signed in are a courtesy; the login is stored.
71
+ }
72
+ return { serverUrl, environments: config.environments, signedIn };
73
+ }
74
+ /**
75
+ * The stored login on this server, or null; a scoped login builds on it.
76
+ * Never `PRIMITIVE_TOKEN`'s credentials (#3890): a login is not built on, nor
77
+ * saved beside, a CI job's token.
78
+ */
79
+ function storedLogin(serverUrl) {
80
+ try {
81
+ const stored = loadCredentials();
82
+ return stored && stored.source !== "env" && stored.serverUrl === serverUrl ? stored : null;
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ /**
89
+ * The environments a login here signs in or out, when it is more than one:
90
+ * every environment of the project on the login's server (#4512), "dev,
91
+ * staging, feat". Null when the login is the current environment's alone.
92
+ */
93
+ function sharedLoginEnvironments() {
94
+ let shared;
95
+ try {
96
+ shared = loginEnvironments();
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ return shared && shared.environments.length > 1 ? shared.environments.join(", ") : null;
102
+ }
103
+ /**
104
+ * Refuse a command that needs a login when there is none, saying why when a
105
+ * linked git worktree could not use the main worktree's (#4492).
106
+ */
107
+ function refuseNotLoggedIn() {
108
+ error("Not logged in. Run 'primitive login' first.");
109
+ const hint = worktreeLoginNotes.notLoggedIn();
110
+ if (hint)
111
+ info(hint);
112
+ process.exit(2);
113
+ }
114
+ /**
115
+ * The last line of a login or logout in a linked git worktree that holds a
116
+ * credentials file of its own, which the shared login makes unused (#4492).
117
+ */
118
+ function noteIgnoredCredentialsFile() {
119
+ const ignored = worktreeLoginNotes.ignoredFile();
120
+ if (ignored)
121
+ info(ignored);
122
+ }
123
+ /** The session id (`sid`) a stored access token carries. */
124
+ function sessionIdOf(credentials) {
125
+ const sid = credentials ? parseJwt(credentials.accessToken).sid : undefined;
126
+ return typeof sid === "string" && sid ? sid : undefined;
127
+ }
128
+ function stepUpFrom(exchange) {
129
+ return {
130
+ accessToken: exchange.accessToken,
131
+ expiresAt: exchange.expiresAt,
132
+ sessionId: exchange.sessionId ?? "",
133
+ scope: exchange.scope ?? [],
134
+ apps: exchange.apps ?? [],
135
+ };
136
+ }
137
+ function appsLabel(apps) {
138
+ return apps.length > 0 ? apps.join(", ") : "unpinned";
139
+ }
140
+ /** A stored step-up that has not expired, or null. */
141
+ function liveStepUp(credentials) {
142
+ const stepUp = credentials.stepUp;
143
+ return stepUp && new Date(stepUp.expiresAt).getTime() > Date.now() ? stepUp : null;
144
+ }
22
145
  function readStdin() {
23
146
  return new Promise((resolve, reject) => {
24
147
  if (process.stdin.isTTY) {
@@ -32,18 +155,84 @@ function readStdin() {
32
155
  process.stdin.on("error", reject);
33
156
  });
34
157
  }
158
+ /**
159
+ * `primitive token --scope …` (#3889): a token no wider than the stored login
160
+ * is derived headlessly; a wider one is approved in the browser. Either way
161
+ * only the token reaches stdout, and nothing is stored.
162
+ *
163
+ * `--step-up` (#4564) always goes to the browser: a derivation signs the
164
+ * stored login's own kind, so it could only print a token that is no step-up.
165
+ */
166
+ async function printScopedToken(options) {
167
+ const credentials = loadCredentials();
168
+ const built = buildScopeRequest({
169
+ command: "token",
170
+ scope: options.scope,
171
+ app: options.app,
172
+ ttl: options.ttl,
173
+ stepUp: options.stepUp,
174
+ envAppId: environmentAppId(),
175
+ parentSid: sessionIdOf(credentials),
176
+ });
177
+ if ("message" in built) {
178
+ error(built.message);
179
+ process.exit(1);
180
+ }
181
+ if (!credentials)
182
+ refuseNotLoggedIn();
183
+ const query = built.query;
184
+ const scope = query.scope.split(",");
185
+ const apps = query.apps ? query.apps.split(",") : [];
186
+ if (options.stepUp) {
187
+ info("A step-up needs your approval in the browser.");
188
+ }
189
+ else {
190
+ try {
191
+ const derived = await new ApiClient().exchangeToken({
192
+ scope,
193
+ ...(apps.length > 0 ? { apps } : {}),
194
+ ...(options.ttl !== undefined ? { ttl: options.ttl } : {}),
195
+ });
196
+ console.log(derived.accessToken);
197
+ return;
198
+ }
199
+ catch (err) {
200
+ if (!(err instanceof ApiError && err.code === "TOKEN_WIDER_THAN_PRESENTED")) {
201
+ error(err?.message || "Token exchange failed");
202
+ process.exit(1);
203
+ }
204
+ }
205
+ info("This token is wider than your login, so it needs your approval in the browser.");
206
+ }
207
+ const result = await browserLogin(credentials.serverUrl, {
208
+ query,
209
+ ...(credentials.globalAdminAppId ? { partition: credentials.globalAdminAppId } : {}),
210
+ save: false,
211
+ });
212
+ if (!result.success || !result.exchange) {
213
+ error(`Token approval failed: ${result.error || "Unknown error"}`);
214
+ process.exit(1);
215
+ }
216
+ console.log(result.exchange.accessToken);
217
+ }
35
218
  export function registerAuthCommands(program) {
36
219
  // Login command
37
220
  program
38
221
  .command("login")
39
222
  .description("Authenticate with the Primitive admin API via browser OAuth")
40
223
  .option("--token-stdin", "Read a refresh token from stdin instead of browser OAuth")
224
+ .option("--scope <list>", "Ask for a scoped session (read, write, admin, data:read, data:write); a list with admin asks for a 15-minute step-up")
225
+ .option("--step-up", "Ask for a 15-minute step-up holding exactly --scope, stored beside your login (writes to a protected app need one)")
226
+ .option("--app <ids>", "Pin the session to these app ids (comma-separated), or all for every app; by default a login is pinned to the project's apps on its server and a step-up to the environment's app")
41
227
  .action(async (options) => {
42
228
  // Login is one of the four commands that may work with no project in
43
229
  // scope (#3154, intent criterion 5): it is what CREATES the credentials
44
230
  // a first `primitive init` then uses. Inside a project this changes
45
231
  // nothing — the per-environment slot still answers.
46
232
  allowGlobalCredentials();
233
+ if (environmentToken()) {
234
+ info("PRIMITIVE_TOKEN is set and takes precedence over this login while it is; unset it to use the login.");
235
+ }
47
236
  // Resolve the target server from the active environment (project mode) or
48
237
  // DEFAULT_SERVER_URL (legacy mode). Never a `-s/--server` flag — that was
49
238
  // removed in #1343 because it always targeted prod regardless of --env.
@@ -57,6 +246,10 @@ export function registerAuthCommands(program) {
57
246
  process.exit(1);
58
247
  }
59
248
  if (options.tokenStdin) {
249
+ if (options.scope !== undefined || options.app !== undefined || options.stepUp) {
250
+ error("--token-stdin takes no --scope, --app or --step-up: the token keeps the scope it was issued with.");
251
+ process.exit(1);
252
+ }
60
253
  const refreshToken = (await readStdin()).trim();
61
254
  if (!refreshToken) {
62
255
  error("No token provided on stdin. Pipe a refresh token, e.g.:");
@@ -69,6 +262,7 @@ export function registerAuthCommands(program) {
69
262
  // shared refresh helper. Only `serverUrl` and `refreshToken` are
70
263
  // needed by the helper; the post-refresh response fills in the
71
264
  // rest. (Codex cleanup #2 — issue #772.)
265
+ const partition = partitionFromEnvironment();
72
266
  const seed = {
73
267
  serverUrl,
74
268
  accessToken: "",
@@ -77,9 +271,13 @@ export function registerAuthCommands(program) {
77
271
  adminId: "",
78
272
  email: "",
79
273
  role: "admin",
274
+ ...(partition ? { globalAdminAppId: partition } : {}),
80
275
  };
81
276
  const refreshed = await refreshAdminCredentials(seed);
82
277
  const payload = parseJwt(refreshed.accessToken);
278
+ // As with a browser login, a step-up already stored stays usable
279
+ // (and revocable by logout) until it expires.
280
+ const existing = storedLogin(serverUrl);
83
281
  const credentials = {
84
282
  ...refreshed,
85
283
  adminId: payload.adminId || "",
@@ -87,15 +285,24 @@ export function registerAuthCommands(program) {
87
285
  role: payload.role || "admin",
88
286
  name: payload.name,
89
287
  globalAdminAppId: payload.globalAdminAppId,
288
+ ...(existing?.stepUp ? { stepUp: existing.stepUp } : {}),
90
289
  };
91
290
  saveCredentials(credentials);
92
291
  success(`Logged in as ${credentials.email}`);
292
+ const shared = sharedLoginEnvironments();
293
+ if (shared)
294
+ info(`Signed in to: ${shared}`);
295
+ const storedElsewhere = worktreeLoginNotes.storedElsewhere();
296
+ if (storedElsewhere)
297
+ info(storedElsewhere);
93
298
  if (credentials.role === "super-admin") {
94
299
  info("You have super-admin privileges.");
95
300
  }
301
+ noteIgnoredCredentialsFile();
96
302
  }
97
303
  catch (err) {
98
- if (err instanceof RefreshError && err.code === "SESSION_REVOKED") {
304
+ if (err instanceof RefreshError &&
305
+ (err.code === "SESSION_REVOKED" || err.code === "SESSION_UNSCOPED")) {
99
306
  error(err.message);
100
307
  }
101
308
  else if (err instanceof RefreshError) {
@@ -108,17 +315,69 @@ export function registerAuthCommands(program) {
108
315
  }
109
316
  return;
110
317
  }
111
- const result = await browserLogin(serverUrl);
112
- if (result.success && result.credentials) {
113
- success(`Logged in as ${result.credentials.email}`);
114
- if (result.credentials.role === "super-admin") {
115
- info("You have super-admin privileges.");
116
- }
318
+ // #3889 — every login is approved in the browser. `--scope`/`--app`
319
+ // ask for a scoped session or an admin step-up; without `--app`, a
320
+ // login in a project is pinned to the project's apps on this server
321
+ // (#4512). The login this one builds on names the step-up's parent and
322
+ // the partition to exchange in.
323
+ const existing = storedLogin(serverUrl);
324
+ const built = buildScopeRequest({
325
+ command: "login",
326
+ scope: options.scope,
327
+ app: options.app,
328
+ stepUp: options.stepUp === true,
329
+ envAppId: environmentAppId(),
330
+ project: loginProject(serverUrl),
331
+ parentSid: sessionIdOf(existing),
332
+ });
333
+ if ("message" in built) {
334
+ error(built.message);
335
+ process.exit(1);
117
336
  }
118
- else {
337
+ const partition = existing?.globalAdminAppId ?? partitionFromEnvironment();
338
+ const result = await browserLogin(serverUrl, {
339
+ ...("query" in built ? { query: built.query } : {}),
340
+ ...(partition ? { partition } : {}),
341
+ save: false,
342
+ });
343
+ if (!result.success || !result.credentials || !result.exchange) {
119
344
  error(`Login failed: ${result.error || "Unknown error"}`);
120
345
  process.exit(1);
121
346
  }
347
+ // #4512 — a server older than this CLI mints every app for a pinned
348
+ // request; nothing is stored unless the session carries the pins asked for.
349
+ const refusal = "query" in built ? loginExchangeRefusal(built.query, result.exchange) : null;
350
+ if (refusal) {
351
+ error(refusal);
352
+ process.exit(1);
353
+ }
354
+ if (result.exchange.kind === "step-up" && existing) {
355
+ // The step-up sits beside the login; the login itself is unchanged.
356
+ const stepUp = stepUpFrom(result.exchange);
357
+ saveCredentials({ ...existing, stepUp });
358
+ success(`Step-up holding ${stepUp.scope.join(", ")} active until ${stepUp.expiresAt} (${appsLabel(stepUp.apps)}). A command refused for a step-up retries with it.`);
359
+ noteIgnoredCredentialsFile();
360
+ return;
361
+ }
362
+ // A new login replaces the slot; a step-up already stored stays usable
363
+ // until it expires.
364
+ saveCredentials({
365
+ ...result.credentials,
366
+ ...(existing?.stepUp ? { stepUp: existing.stepUp } : {}),
367
+ });
368
+ success(`Logged in as ${result.credentials.email}`);
369
+ // #3891, #4512 — say what the login holds and reaches, every
370
+ // environment it signs in to and which need a login of their own, and
371
+ // how to step up for what it cannot do.
372
+ for (const line of loginScopeLines(result.exchange, loginLinesContext(serverUrl)))
373
+ info(line);
374
+ const storedElsewhere = worktreeLoginNotes.storedElsewhere();
375
+ if (storedElsewhere)
376
+ info(storedElsewhere);
377
+ if (result.credentials.role === "super-admin") {
378
+ info("You have super-admin privileges.");
379
+ }
380
+ noteIgnoredCredentialsFile();
122
381
  });
123
382
  // Bootstrap command - create first admin on empty database
124
383
  program
@@ -134,6 +393,16 @@ export function registerAuthCommands(program) {
134
393
  allowGlobalCredentials();
135
394
  const serverUrl = options.server.replace(/\/$/, "");
136
395
  try {
396
+ // Inside a project the login is stored in the current environment's
397
+ // slot, which only holds a login from that environment's server
398
+ // (#4492): refuse before an admin is created whose login could not be
399
+ // stored.
400
+ const env = getCurrentEnvironment();
401
+ if (env && !sameServer(serverUrl, env.config.apiUrl)) {
402
+ error(`"${env.name}" points at ${env.config.apiUrl}, not ${serverUrl}. Run bootstrap outside ` +
403
+ `a project, or from an environment that points at ${serverUrl}.`);
404
+ process.exit(1);
405
+ }
137
406
  const response = await fetchWithTLS(`${serverUrl}/admin/api/bootstrap`, {
138
407
  method: "POST",
139
408
  headers: { "Content-Type": "application/json" },
@@ -172,6 +441,17 @@ export function registerAuthCommands(program) {
172
441
  // command fails: re-running it retries the revocation. A 401 means the
173
442
  // stored token was already refused — nothing is left to revoke, so the
174
443
  // credentials are cleared.
444
+ //
445
+ // #4512: every environment on a server uses the server's one login, so
446
+ // logout in any of them signs out all of them, and says which. A login an
447
+ // older CLI kept for another environment on the server (a leftover) is
448
+ // revoked too.
449
+ //
450
+ // #4492: a login whose slot records another server than the environment's
451
+ // is the one no other command uses. Logout revokes it at the server that
452
+ // issued it — the one that can — and says the environment is not signed in.
453
+ // In a linked git worktree the login is the main worktree's, so logout signs
454
+ // out every worktree that holds the project, and says so.
175
455
  program
176
456
  .command("logout")
177
457
  .description("Revoke this login's admin session on the server and clear stored credentials")
@@ -180,14 +460,35 @@ export function registerAuthCommands(program) {
180
460
  // would leave a global credentials file no command could clear
181
461
  // (#3154, adjudicated finding F1).
182
462
  allowGlobalCredentials();
183
- const credentials = loadCredentials();
184
- if (!credentials) {
463
+ // #3890 — a CI job's token is not a login to sign out of: its session
464
+ // is revoked by id, and nothing stored is touched.
465
+ if (environmentToken()) {
466
+ error("PRIMITIVE_TOKEN is set; revoke the CI session with `primitive auth sessions revoke <id>` instead.");
467
+ process.exit(1);
468
+ }
469
+ let credentials;
470
+ let issuedElsewhere = false;
471
+ try {
472
+ credentials = loadCredentials();
473
+ }
474
+ catch (err) {
475
+ if (!(err instanceof PrimitiveEnvError && err.kind === "server-mismatch"))
476
+ throw err;
477
+ credentials = mismatchedLogin();
478
+ issuedElsewhere = credentials !== null;
479
+ }
480
+ const leftovers = leftoverLogins();
481
+ if (!credentials && leftovers.length === 0) {
185
482
  info("Not logged in.");
483
+ noteIgnoredCredentialsFile();
186
484
  return;
187
485
  }
188
- let outcome;
486
+ let outcome = null;
189
487
  try {
190
- outcome = await logoutAdminSession(credentials);
488
+ if (credentials)
489
+ outcome = await logoutAdminSession(credentials);
490
+ for (const leftover of leftovers)
491
+ await logoutAdminSession(leftover);
191
492
  }
192
493
  catch (err) {
193
494
  error(`${err?.message || "Logout failed."} The session was NOT revoked, and ` +
@@ -195,15 +496,29 @@ export function registerAuthCommands(program) {
195
496
  process.exit(1);
196
497
  }
197
498
  clearCredentials();
198
- if (outcome.kind === "already-invalid") {
499
+ clearLeftoverLogins();
500
+ if (outcome?.kind === "already-invalid") {
199
501
  success("Logged out. The stored session was already invalid on the server; local credentials cleared.");
200
502
  }
201
- else if (outcome.revoked.length > 0) {
503
+ else if (outcome && outcome.revoked.length > 0) {
202
504
  success(`Logged out. Revoked session ${outcome.revoked.join(", ")}.`);
203
505
  }
204
506
  else {
205
507
  success("Logged out successfully.");
206
508
  }
509
+ if (issuedElsewhere && credentials) {
510
+ const env = getCurrentEnvironment();
511
+ info(`This login was issued by ${credentials.serverUrl}; "${env?.name}" now points at ` +
512
+ `${env?.config.apiUrl}, where you are not signed in.`);
513
+ }
514
+ const shared = sharedLoginEnvironments();
515
+ if (shared)
516
+ success(`Signed out of: ${shared}`);
517
+ const tree = loginEnvironments();
518
+ const sharedWorktrees = tree ? worktreeLoginNotes.sharedLogout(tree.tree) : null;
519
+ if (sharedWorktrees)
520
+ info(sharedWorktrees);
521
+ noteIgnoredCredentialsFile();
207
522
  });
208
523
  // Whoami command
209
524
  //
@@ -212,34 +527,120 @@ export function registerAuthCommands(program) {
212
527
  // about to act on?"); only the source moved, from a per-machine credentials
213
528
  // slot to the one place that can name an app. Outside a project there is no
214
529
  // environment and so no app, which is the honest answer there.
530
+ //
531
+ // #4918 — outside a project it reports the user and server a command run
532
+ // there would use: the server PRIMITIVE_SERVER_URL names, or production,
533
+ // and the global login only when that server issued it — the pin
534
+ // `apps delete` uses (#4905). Inside a project nothing here runs.
215
535
  program
216
536
  .command("whoami")
217
- .description("Show current authenticated user")
537
+ .description("Show the user, server and app a command run here would use")
218
538
  .option("--json", "Output as JSON")
219
- .action((options) => {
220
- const credentials = loadCredentials();
221
- if (!credentials) {
222
- error("Not logged in. Run 'primitive login' first.");
223
- process.exit(2);
539
+ .action(async (options) => {
540
+ const outside = inProject() ? null : outsideProjectServer();
541
+ let credentials;
542
+ if (outside !== null) {
543
+ allowGlobalCredentialsForServer(outside);
544
+ try {
545
+ credentials = loadCredentials();
546
+ }
547
+ catch (err) {
548
+ error(err.message);
549
+ process.exit(1);
550
+ }
551
+ if (!credentials) {
552
+ error(`Not logged in to ${outside}. Run '${globalLoginCommand(outside)} <app-id>' (or --app all) first.`);
553
+ process.exit(2);
554
+ }
555
+ }
556
+ else {
557
+ credentials = loadCredentials();
558
+ if (!credentials)
559
+ refuseNotLoggedIn();
560
+ }
561
+ const env = outside === null ? requireCurrentEnvironment() : null;
562
+ const app = env ? { appId: env.config.appId, appName: env.config.appName } : null;
563
+ const fromEnvironment = credentials.source === "env";
564
+ const serverSource = outside === null ? "environment" : process.env.PRIMITIVE_SERVER_URL?.trim() ? "PRIMITIVE_SERVER_URL" : "default";
565
+ const authSource = fromEnvironment ? "PRIMITIVE_TOKEN" : outside === null ? "project" : "global";
566
+ // #3889 — the session's kind, scope and pins, read from the stored
567
+ // token's claims, and the step-up held beside it. No request.
568
+ // #3890 — an opaque CI token in PRIMITIVE_TOKEN has no claims to read:
569
+ // the server says who it is, in one request.
570
+ let who;
571
+ let session;
572
+ if (fromEnvironment && isCiToken(credentials.accessToken)) {
573
+ try {
574
+ const me = (await new ApiClient().getMe());
575
+ who = { email: me.email, adminId: me.adminId, role: me.role };
576
+ session = me.session ?? null;
577
+ }
578
+ catch (err) {
579
+ error(err?.message || "Could not read the token's session.");
580
+ process.exit(1);
581
+ }
224
582
  }
225
- const app = getCurrentApp();
583
+ else {
584
+ const claims = parseJwt(credentials.accessToken);
585
+ who = fromEnvironment
586
+ ? {
587
+ email: typeof claims.email === "string" ? claims.email : "",
588
+ adminId: typeof claims.adminId === "string" ? claims.adminId : "",
589
+ role: typeof claims.role === "string" ? claims.role : "",
590
+ }
591
+ : { email: credentials.email, adminId: credentials.adminId, role: credentials.role };
592
+ session = {
593
+ ...(typeof claims.sid === "string" ? { sessionId: claims.sid } : {}),
594
+ kind: typeof claims.kind === "string" ? claims.kind : null,
595
+ scope: Array.isArray(claims.scope) ? claims.scope : "full",
596
+ apps: Array.isArray(claims.apps) ? claims.apps : [],
597
+ name: null,
598
+ };
599
+ }
600
+ const kind = session?.kind ?? null;
601
+ const scope = session?.scope ?? "full";
602
+ const apps = session?.apps ?? [];
603
+ const stepUp = liveStepUp(credentials);
226
604
  if (options.json) {
227
605
  json({
228
- email: credentials.email,
229
- adminId: credentials.adminId,
230
- role: credentials.role,
606
+ email: who.email,
607
+ adminId: who.adminId,
608
+ role: who.role,
231
609
  serverUrl: credentials.serverUrl,
232
- currentAppId: app?.appId,
233
- currentAppName: app?.appName,
610
+ serverSource,
611
+ authSource,
612
+ environment: env?.name ?? null,
613
+ currentAppId: app ? app.appId : null,
614
+ currentAppName: app ? app.appName : null,
615
+ kind,
616
+ scope,
617
+ apps,
618
+ stepUp: stepUp
619
+ ? { expiresAt: stepUp.expiresAt, scope: stepUp.scope, apps: stepUp.apps }
620
+ : null,
621
+ ...(fromEnvironment ? { auth: "env", session } : {}),
234
622
  });
235
623
  return;
236
624
  }
237
- keyValue("Email", credentials.email);
238
- keyValue("Admin ID", credentials.adminId);
239
- keyValue("Role", credentials.role);
625
+ keyValue("Email", who.email);
626
+ keyValue("Admin ID", who.adminId);
627
+ keyValue("Role", who.role);
628
+ if (env)
629
+ keyValue("Environment", env.name);
240
630
  keyValue("Server", credentials.serverUrl);
241
- if (app) {
242
- keyValue("Current App", app.appName || app.appId);
631
+ keyValue("Server Source", env ? `environment "${env.name}"` : serverSource);
632
+ keyValue("Current App", app ? app.appName || app.appId : "none (pass --app)");
633
+ if (fromEnvironment)
634
+ keyValue("Auth", "PRIMITIVE_TOKEN");
635
+ else if (!env)
636
+ keyValue("Auth", `global login (${getCredentialsFilePath()})`);
637
+ keyValue("Kind", kind);
638
+ if (session?.name)
639
+ keyValue("Name", session.name);
640
+ keyValue("Scope", scope === "full" ? "full" : scope.join(", "));
641
+ keyValue("Apps", appsLabel(apps));
642
+ if (stepUp) {
643
+ keyValue("Step-up", `active until ${stepUp.expiresAt}, scope ${stepUp.scope.join(", ")}, ${appsLabel(stepUp.apps)}`);
243
644
  }
244
645
  });
245
646
  // Token command - print access token for scripting
@@ -258,11 +659,34 @@ export function registerAuthCommands(program) {
258
659
  .command("token")
259
660
  .description("Print the current access token (for scripting)")
260
661
  .option("--refresh", "Print the refresh token instead of the access token")
662
+ .option("--scope <list>", "Print a token with only these scopes; one wider than your login is approved in the browser and cannot be refreshed")
663
+ .option("--step-up", "Print a 15-minute step-up holding exactly --scope, always approved in the browser")
664
+ .option("--app <ids>", "Pin the printed token to these app ids (comma-separated), or all for an unpinned one")
665
+ .option("--ttl <d>", "Lifetime of the printed token, such as 15m (at most 1h; 15m for a step-up)")
261
666
  .action(async (options) => {
667
+ if (options.scope !== undefined ||
668
+ options.app !== undefined ||
669
+ options.ttl !== undefined ||
670
+ options.stepUp) {
671
+ if (options.refresh) {
672
+ error("--refresh prints the stored refresh token; it takes no --scope, --app, --ttl or --step-up.");
673
+ process.exit(1);
674
+ }
675
+ await printScopedToken(options);
676
+ return;
677
+ }
262
678
  const credentials = loadCredentials();
263
- if (!credentials) {
264
- error("Not logged in. Run 'primitive login' first.");
265
- process.exit(2);
679
+ if (!credentials)
680
+ refuseNotLoggedIn();
681
+ // #3890 — the token in PRIMITIVE_TOKEN is printed as it is; it has no
682
+ // refresh token and is never refreshed here.
683
+ if (credentials.source === "env") {
684
+ if (options.refresh) {
685
+ error("PRIMITIVE_TOKEN has no refresh token.");
686
+ process.exit(1);
687
+ }
688
+ console.log(credentials.accessToken);
689
+ return;
266
690
  }
267
691
  if (options.refresh) {
268
692
  // Dumb-print contract preserved — see Fork 4 in the design doc.