primitive-admin 1.1.0-alpha.4 → 1.1.0-alpha.41
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.
- package/README.md +325 -31
- package/assets/skill/skills/primitive-platform/SKILL.md +281 -0
- package/dist/bin/primitive.d.ts +2 -0
- package/dist/bin/primitive.js +268 -16
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.d.ts +2 -0
- package/dist/src/commands/admins.js +123 -18
- package/dist/src/commands/admins.js.map +1 -1
- package/dist/src/commands/analytics.d.ts +2 -0
- package/dist/src/commands/analytics.js +464 -55
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps.d.ts +2 -0
- package/dist/src/commands/apps.js +55 -13
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +177 -7
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/blob-buckets.d.ts +2 -0
- package/dist/src/commands/blob-buckets.js +422 -0
- package/dist/src/commands/blob-buckets.js.map +1 -0
- package/dist/src/commands/catalog.d.ts +2 -0
- package/dist/src/commands/catalog.js +34 -35
- package/dist/src/commands/catalog.js.map +1 -1
- package/dist/src/commands/collection-type-configs.d.ts +2 -0
- package/dist/src/commands/collection-type-configs.js +178 -0
- package/dist/src/commands/collection-type-configs.js.map +1 -0
- package/dist/src/commands/collections.d.ts +2 -0
- package/dist/src/commands/collections.js +515 -0
- package/dist/src/commands/collections.js.map +1 -0
- package/dist/src/commands/comparisons.d.ts +2 -0
- package/dist/src/commands/comparisons.js +6 -6
- package/dist/src/commands/comparisons.js.map +1 -1
- package/dist/src/commands/cron-triggers.d.ts +2 -0
- package/dist/src/commands/cron-triggers.js +357 -0
- package/dist/src/commands/cron-triggers.js.map +1 -0
- package/dist/src/commands/database-types.d.ts +2 -0
- package/dist/src/commands/database-types.js +471 -0
- package/dist/src/commands/database-types.js.map +1 -0
- package/dist/src/commands/databases.d.ts +2 -0
- package/dist/src/commands/databases.js +1462 -83
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +2 -0
- package/dist/src/commands/documents.js +518 -11
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/email-templates.d.ts +2 -0
- package/dist/src/commands/email-templates.js +281 -0
- package/dist/src/commands/email-templates.js.map +1 -0
- package/dist/src/commands/env.d.ts +12 -0
- package/dist/src/commands/env.js +260 -0
- package/dist/src/commands/env.js.map +1 -0
- package/dist/src/commands/group-type-configs.d.ts +2 -0
- package/dist/src/commands/group-type-configs.js +181 -0
- package/dist/src/commands/group-type-configs.js.map +1 -0
- package/dist/src/commands/groups.d.ts +2 -0
- package/dist/src/commands/groups.js +48 -45
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.d.ts +159 -0
- package/dist/src/commands/guides.js +449 -35
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +17 -0
- package/dist/src/commands/init.js +811 -201
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.d.ts +2 -0
- package/dist/src/commands/integrations.js +533 -46
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/llm.d.ts +2 -0
- package/dist/src/commands/llm.js +4 -2
- package/dist/src/commands/llm.js.map +1 -1
- package/dist/src/commands/metadata.d.ts +2 -0
- package/dist/src/commands/metadata.js +194 -0
- package/dist/src/commands/metadata.js.map +1 -0
- package/dist/src/commands/prompts.d.ts +2 -0
- package/dist/src/commands/prompts.js +50 -52
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/rule-sets.d.ts +3 -0
- package/dist/src/commands/rule-sets.js +388 -0
- package/dist/src/commands/rule-sets.js.map +1 -0
- package/dist/src/commands/scripts.d.ts +2 -0
- package/dist/src/commands/scripts.js +667 -0
- package/dist/src/commands/scripts.js.map +1 -0
- package/dist/src/commands/secrets.d.ts +2 -0
- package/dist/src/commands/secrets.js +108 -0
- package/dist/src/commands/secrets.js.map +1 -0
- package/dist/src/commands/skill.d.ts +2 -0
- package/dist/src/commands/skill.js +29 -0
- package/dist/src/commands/skill.js.map +1 -0
- package/dist/src/commands/sync.d.ts +175 -0
- package/dist/src/commands/sync.js +4412 -233
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.d.ts +2 -0
- package/dist/src/commands/tokens.js +122 -19
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.d.ts +2 -0
- package/dist/src/commands/users.js +440 -22
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/waitlist.d.ts +2 -0
- package/dist/src/commands/waitlist.js +10 -10
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +2 -0
- package/dist/src/commands/webhooks.js +391 -0
- package/dist/src/commands/webhooks.js.map +1 -0
- package/dist/src/commands/workflows.d.ts +49 -0
- package/dist/src/commands/workflows.js +1009 -123
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +1283 -0
- package/dist/src/lib/api-client.js +1129 -83
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/auth-flow.d.ts +8 -0
- package/dist/src/lib/block-layout.d.ts +160 -0
- package/dist/src/lib/block-layout.js +451 -0
- package/dist/src/lib/block-layout.js.map +1 -0
- package/dist/src/lib/cli-manifest.d.ts +60 -0
- package/dist/src/lib/cli-manifest.js +70 -0
- package/dist/src/lib/cli-manifest.js.map +1 -0
- package/dist/src/lib/config.d.ts +53 -0
- package/dist/src/lib/config.js +92 -53
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/confirm-prompt.d.ts +83 -0
- package/dist/src/lib/confirm-prompt.js +110 -0
- package/dist/src/lib/confirm-prompt.js.map +1 -0
- package/dist/src/lib/constants.d.ts +2 -0
- package/dist/src/lib/constants.js +3 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/crash-handlers.d.ts +20 -0
- package/dist/src/lib/crash-handlers.js +49 -0
- package/dist/src/lib/crash-handlers.js.map +1 -0
- package/dist/src/lib/credentials-store.d.ts +79 -0
- package/dist/src/lib/credentials-store.js +307 -0
- package/dist/src/lib/credentials-store.js.map +1 -0
- package/dist/src/lib/csv.d.ts +48 -0
- package/dist/src/lib/csv.js +177 -0
- package/dist/src/lib/csv.js.map +1 -0
- package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +111 -0
- package/dist/src/lib/db-codegen/dbGenerator.js +371 -0
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/db-codegen/dbNaming.d.ts +45 -0
- package/dist/src/lib/db-codegen/dbNaming.js +104 -0
- package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +97 -0
- package/dist/src/lib/db-codegen/dbTemplates.js +159 -0
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +78 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js +112 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
- package/dist/src/lib/env-resolver.d.ts +62 -0
- package/dist/src/lib/env-resolver.js +121 -0
- package/dist/src/lib/env-resolver.js.map +1 -0
- package/dist/src/lib/fetch.d.ts +5 -0
- package/dist/src/lib/generated-allowlist.d.ts +28 -0
- package/dist/src/lib/generated-allowlist.js +220 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -0
- package/dist/src/lib/init-config.d.ts +59 -0
- package/dist/src/lib/init-config.js +113 -0
- package/dist/src/lib/init-config.js.map +1 -0
- package/dist/src/lib/migration-nag.d.ts +49 -0
- package/dist/src/lib/migration-nag.js +163 -0
- package/dist/src/lib/migration-nag.js.map +1 -0
- package/dist/src/lib/output.d.ts +86 -0
- package/dist/src/lib/output.js +150 -8
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/paginate.d.ts +33 -0
- package/dist/src/lib/paginate.js +42 -0
- package/dist/src/lib/paginate.js.map +1 -0
- package/dist/src/lib/project-config.d.ts +97 -0
- package/dist/src/lib/project-config.js +209 -0
- package/dist/src/lib/project-config.js.map +1 -0
- package/dist/src/lib/query-operators.d.ts +43 -0
- package/dist/src/lib/query-operators.js +80 -0
- package/dist/src/lib/query-operators.js.map +1 -0
- package/dist/src/lib/refresh-admin-credentials.d.ts +65 -0
- package/dist/src/lib/refresh-admin-credentials.js +103 -0
- package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
- package/dist/src/lib/resolve-platform.d.ts +45 -0
- package/dist/src/lib/resolve-platform.js +43 -0
- package/dist/src/lib/resolve-platform.js.map +1 -0
- package/dist/src/lib/skill-installer.d.ts +23 -0
- package/dist/src/lib/skill-installer.js +135 -0
- package/dist/src/lib/skill-installer.js.map +1 -0
- package/dist/src/lib/snapshots.d.ts +99 -0
- package/dist/src/lib/snapshots.js +357 -0
- package/dist/src/lib/snapshots.js.map +1 -0
- package/dist/src/lib/sync-paths.d.ts +72 -0
- package/dist/src/lib/sync-paths.js +130 -0
- package/dist/src/lib/sync-paths.js.map +1 -0
- package/dist/src/lib/template.d.ts +97 -0
- package/dist/src/lib/template.js +336 -62
- package/dist/src/lib/template.js.map +1 -1
- package/dist/src/lib/token-inject.d.ts +56 -0
- package/dist/src/lib/token-inject.js +204 -0
- package/dist/src/lib/token-inject.js.map +1 -0
- package/dist/src/lib/toml-database-config.d.ts +152 -0
- package/dist/src/lib/toml-database-config.js +600 -0
- package/dist/src/lib/toml-database-config.js.map +1 -0
- package/dist/src/lib/toml-metadata-config.d.ts +139 -0
- package/dist/src/lib/toml-metadata-config.js +427 -0
- package/dist/src/lib/toml-metadata-config.js.map +1 -0
- package/dist/src/lib/toml-params-validator.d.ts +129 -0
- package/dist/src/lib/toml-params-validator.js +298 -0
- package/dist/src/lib/toml-params-validator.js.map +1 -0
- package/dist/src/lib/version-check.d.ts +10 -0
- package/dist/src/lib/version-check.js +172 -0
- package/dist/src/lib/version-check.js.map +1 -0
- package/dist/src/lib/workflow-apply.d.ts +66 -0
- package/dist/src/lib/workflow-apply.js +117 -0
- package/dist/src/lib/workflow-apply.js.map +1 -0
- package/dist/src/lib/workflow-fragments.d.ts +41 -0
- package/dist/src/lib/workflow-fragments.js +121 -0
- package/dist/src/lib/workflow-fragments.js.map +1 -0
- package/dist/src/lib/workflow-toml-validator.d.ts +95 -0
- package/dist/src/lib/workflow-toml-validator.js +323 -0
- package/dist/src/lib/workflow-toml-validator.js.map +1 -0
- package/dist/src/types/index.d.ts +520 -0
- package/dist/src/validators.d.ts +64 -0
- package/dist/src/validators.js +63 -0
- package/dist/src/validators.js.map +1 -0
- package/package.json +18 -4
package/README.md
CHANGED
|
@@ -71,11 +71,15 @@ primitive apps --help
|
|
|
71
71
|
The CLI uses browser-based OAuth for authentication. When you run `primitive login`, it opens your browser to authenticate via Google OAuth and stores credentials locally.
|
|
72
72
|
|
|
73
73
|
```bash
|
|
74
|
-
# Login to the
|
|
74
|
+
# Login to the environment resolved from .primitive/config.json
|
|
75
|
+
# (project mode), or the default/PRIMITIVE_SERVER_URL server (legacy mode)
|
|
75
76
|
primitive login
|
|
76
77
|
|
|
77
|
-
# Login to a
|
|
78
|
-
primitive
|
|
78
|
+
# Login to a specific named environment
|
|
79
|
+
primitive -e prod login
|
|
80
|
+
|
|
81
|
+
# Login to a custom server without a project config (legacy mode)
|
|
82
|
+
PRIMITIVE_SERVER_URL=https://api.example.com primitive login
|
|
79
83
|
|
|
80
84
|
# View current session
|
|
81
85
|
primitive whoami
|
|
@@ -150,12 +154,13 @@ Manage users within an app.
|
|
|
150
154
|
|
|
151
155
|
```bash
|
|
152
156
|
primitive users list [app-id] # List users
|
|
157
|
+
primitive users create <email> [--role admin|member] # Create/add user by email
|
|
153
158
|
primitive users invite [app-id] <email> [--role admin] # Invite user
|
|
154
159
|
primitive users remove [app-id] <user-id> # Remove user
|
|
155
160
|
primitive users set-role [app-id] <user-id> <role> # Change role
|
|
156
161
|
primitive users transfer-owner [app-id] <new-owner-id> # Transfer ownership
|
|
157
|
-
primitive users
|
|
158
|
-
primitive users invitations
|
|
162
|
+
primitive users mint-jwt <user-id> [--role <role>] # Mint test JWT (dev/test only)
|
|
163
|
+
primitive users invitations [app-id] # List pending invitations
|
|
159
164
|
```
|
|
160
165
|
|
|
161
166
|
### Waitlist
|
|
@@ -191,12 +196,38 @@ primitive integrations logs <id> # View invocation logs
|
|
|
191
196
|
- `--timeout <ms>` - Request timeout in milliseconds
|
|
192
197
|
|
|
193
198
|
**Secrets management:**
|
|
199
|
+
|
|
200
|
+
Integration-scoped secrets are **deprecated** and can no longer be created. Use
|
|
201
|
+
app-level secrets instead (`primitive secrets set <KEY> --value <value>`) and reference
|
|
202
|
+
them in integration config via `{{secrets.KEY}}`. See the **Secrets** section
|
|
203
|
+
below. The remaining integration-secret commands only list/archive legacy
|
|
204
|
+
secrets:
|
|
205
|
+
|
|
194
206
|
```bash
|
|
195
207
|
primitive integrations secrets list <integration-id>
|
|
196
|
-
primitive integrations secrets add <id> --data '{"apiKey":"..."}'
|
|
197
208
|
primitive integrations secrets archive <id> <secret-id>
|
|
198
209
|
```
|
|
199
210
|
|
|
211
|
+
### Secrets
|
|
212
|
+
|
|
213
|
+
Manage encrypted app secrets (API keys, tokens, credentials). Values are encrypted at rest and never displayed after creation.
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
primitive secrets list [--app <app-id>] # List secrets (values never shown)
|
|
217
|
+
primitive secrets set <KEY> --value <value> [--summary <text>] # Create or update a secret
|
|
218
|
+
primitive secrets delete <KEY> # Delete a secret
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Examples:**
|
|
222
|
+
```bash
|
|
223
|
+
primitive secrets set OPENAI_API_KEY --value "sk-..." --summary "Production key"
|
|
224
|
+
primitive secrets set STRIPE_SECRET --value "sk_live_..."
|
|
225
|
+
primitive secrets list --json
|
|
226
|
+
primitive secrets delete STRIPE_SECRET
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
Keys must be uppercase letters, digits, and underscores (e.g., `OPENAI_API_KEY`). Max 100 secrets per app, 2 KB per value. The `set` command is an upsert — it creates or updates automatically. Use `{{secrets.KEY}}` in workflows and `secrets.KEY` in CEL rules.
|
|
230
|
+
|
|
200
231
|
### Prompts
|
|
201
232
|
|
|
202
233
|
Manage LLM prompt configurations.
|
|
@@ -248,6 +279,39 @@ primitive workflows runs list <workflow-id>
|
|
|
248
279
|
primitive workflows runs status <workflow-id> <run-id>
|
|
249
280
|
```
|
|
250
281
|
|
|
282
|
+
**Workflow TOML push-time validation (issue #685):** Every command that
|
|
283
|
+
pushes a workflow TOML (`workflows create --from-file`,
|
|
284
|
+
`workflows draft update --from-file`, `workflows configs create --from-file`,
|
|
285
|
+
`workflows configs update --from-file`, and `primitive sync push`) runs the
|
|
286
|
+
file through `cli/src/lib/workflow-toml-validator.ts` before sending it to
|
|
287
|
+
the server. For a step whose `kind` the CLI knows about, the validator
|
|
288
|
+
rejects any top-level field outside the allowlist — most commonly catching
|
|
289
|
+
the footgun where `[steps.<id>.request]` is written under `[[steps]]` (TOML
|
|
290
|
+
places the sub-table under `steps[N][<id>]`, not the intended
|
|
291
|
+
`steps[N].request`, so the runtime silently runs the step with an empty
|
|
292
|
+
`request` block). The correct form for the most-recent step is
|
|
293
|
+
`[steps.request]`. For a step whose `kind` the CLI does NOT know (an older
|
|
294
|
+
CLI run against a newer server that registered a new step kind), the
|
|
295
|
+
per-field check is skipped — so a valid new-kind field is never falsely
|
|
296
|
+
rejected — while the kind-agnostic misnested-header footgun detector still
|
|
297
|
+
fires (issue #998).
|
|
298
|
+
|
|
299
|
+
**The allowlist is generated, not hand-maintained (issue #998):** The field
|
|
300
|
+
union and the known-kind set live in the committed artifact
|
|
301
|
+
`cli/src/lib/generated-allowlist.ts`, generated from the server step runners
|
|
302
|
+
(`src/workflows/steps/*.ts`) and the universal `BaseStepDefinition` shape by
|
|
303
|
+
`cli/scripts/gen-allowlist.mjs`. The generator runs automatically at CLI
|
|
304
|
+
`prebuild`; regenerate manually with `node cli/scripts/gen-allowlist.mjs`
|
|
305
|
+
(or `pnpm -C cli gen:allowlist`). The union is derived from what each runner
|
|
306
|
+
*reads* off the step config — not from what the `*StepDefinition` type
|
|
307
|
+
declares (types over-declare and would weaken the footgun detector). A
|
|
308
|
+
freshness guard (`node cli/scripts/gen-allowlist.mjs --check`, also asserted
|
|
309
|
+
by `cli/tests/unit/workflow-toml-validator-drift-guard.test.ts`) fails if the
|
|
310
|
+
committed artifact drifts from a fresh scan, so the historical hand-edit
|
|
311
|
+
drift (#685/#802/#971) cannot recur. When you add a new step kind or a runner
|
|
312
|
+
starts reading a new field, just regenerate and commit the artifact — there is
|
|
313
|
+
no hand-maintained list to update.
|
|
314
|
+
|
|
251
315
|
### Tokens
|
|
252
316
|
|
|
253
317
|
Manage long-lived API access tokens for headless/server authentication.
|
|
@@ -263,16 +327,17 @@ primitive tokens revoke <token-id> [app-id] # Revoke t
|
|
|
263
327
|
**Create options:**
|
|
264
328
|
- `--name <name>` - Token name (required)
|
|
265
329
|
- `--user <user-id>` - App user ID to associate the token with (required)
|
|
266
|
-
- `--ttl <duration>` - Token lifetime (e.g., 7d, 30d, 4w,
|
|
330
|
+
- `--ttl <duration>` - Token lifetime (e.g., 30m, 2h, 7d, 30d, 4w, 3mo, 1y). Omit for never-expiring. Units: `m`/`min`=minutes (≤1440), `h`=hours (≤24), `d`=days, `w`=weeks, `mo`=months, `y`=years. **Note:** as of #420 `m` means minutes (was months); use `mo` for months.
|
|
267
331
|
|
|
268
332
|
### Databases
|
|
269
333
|
|
|
270
|
-
Manage online databases
|
|
334
|
+
Manage online databases and permissions. `list` returns databases the user has direct access to; group-shared databases are listed via `primitive groups databases`.
|
|
271
335
|
|
|
272
336
|
```bash
|
|
273
|
-
primitive databases list [app-id] # List databases
|
|
337
|
+
primitive databases list [app-id] # List databases (direct access)
|
|
274
338
|
primitive databases create <title> [app-id] # Create database
|
|
275
339
|
primitive databases get <database-id> [app-id] # Get details
|
|
340
|
+
primitive databases update <database-id> [options] # Update title or type
|
|
276
341
|
primitive databases delete <database-id> [app-id] # Delete database
|
|
277
342
|
```
|
|
278
343
|
|
|
@@ -283,14 +348,68 @@ primitive databases permissions grant <database-id> --user-id <uid> --permission
|
|
|
283
348
|
primitive databases permissions revoke <database-id> <user-id> [app-id]
|
|
284
349
|
```
|
|
285
350
|
|
|
286
|
-
|
|
351
|
+
Permission values: `owner` (set at creation), `manager`
|
|
352
|
+
|
|
353
|
+
**Metadata:**
|
|
354
|
+
```bash
|
|
355
|
+
primitive databases metadata update <database-id> --data '{"key":"value"}' # Merge-update metadata
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
**Operations:**
|
|
359
|
+
```bash
|
|
360
|
+
primitive databases operations list <database-id> [app-id] # List registered operations
|
|
361
|
+
primitive databases operations execute <database-id> <op-name> --params '{}' # Execute operation
|
|
362
|
+
primitive databases operations execute <database-id> <op-name> --token <jwt> # Execute as specific user
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
The `--token` flag lets you execute an operation as a specific user using a test JWT from `users mint-jwt`. Useful for testing access rules.
|
|
366
|
+
|
|
367
|
+
**Records (schema introspection):**
|
|
368
|
+
```bash
|
|
369
|
+
primitive databases records models <database-id> [app-id] # List model names
|
|
370
|
+
primitive databases records describe <database-id> <model> [app-id] # Show inferred schema
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Indexes:**
|
|
374
|
+
```bash
|
|
375
|
+
primitive databases indexes list <database-id> [--model <name>] # List indexes
|
|
376
|
+
primitive databases indexes create <database-id> <model> <field> [options] # Create index
|
|
377
|
+
primitive databases indexes drop <database-id> <model> <field> # Drop index
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Export / Import:**
|
|
381
|
+
```bash
|
|
382
|
+
primitive databases export [app-id] <database-id> --output <dir> # Export records, indexes, constraints
|
|
383
|
+
primitive databases import [app-id] <path> --overwrite --dry-run # Import from export directory
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
Export creates a directory with `metadata.json`, `records.jsonl`, `indexes.json`, and `constraints.json`. Import restores records and indexes into a new or existing database. Database type config (operations, triggers, access rules) is managed separately via `primitive sync` — run `sync push` on the target app before importing.
|
|
387
|
+
|
|
388
|
+
### Documents
|
|
389
|
+
|
|
390
|
+
Manage document ownership, group permissions, and export/import.
|
|
391
|
+
|
|
392
|
+
```bash
|
|
393
|
+
primitive documents transfer-owner [app-id] <document-id> <new-owner-id> # Transfer ownership
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**Group permissions on documents:**
|
|
397
|
+
```bash
|
|
398
|
+
primitive documents group-permissions list <document-id>
|
|
399
|
+
primitive documents group-permissions grant <document-id> --group-type <type> --group-id <id> --permission <perm>
|
|
400
|
+
primitive documents group-permissions revoke <document-id> <group-type> <group-id>
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
Permission values: `read-write`, `reader`
|
|
404
|
+
|
|
405
|
+
**Export / Import:**
|
|
287
406
|
```bash
|
|
288
|
-
primitive
|
|
289
|
-
primitive
|
|
290
|
-
primitive
|
|
407
|
+
primitive documents export [app-id] <document-id> --output <dir> # Export Yjs state, blobs, permissions, aliases
|
|
408
|
+
primitive documents export-all [app-id] --user-id <id> --owned-only # Export all docs for a user
|
|
409
|
+
primitive documents import [app-id] <path> --overwrite --aliases overwrite|skip --dry-run # Import from export
|
|
291
410
|
```
|
|
292
411
|
|
|
293
|
-
|
|
412
|
+
Export creates a directory per document with `metadata.json`, `document.yjs` (Yjs state), `permissions.json` (for reference), and `blobs/` (attachments). Permissions are exported for reference but not restored during import — the importing admin is the new owner and manages sharing in the target app. Document IDs are preserved across import. User-scoped aliases can be restored with `--aliases overwrite` (update existing) or `--aliases skip` (keep existing, default).
|
|
294
413
|
|
|
295
414
|
### Groups
|
|
296
415
|
|
|
@@ -317,20 +436,46 @@ primitive groups members set-role <group-type> <group-id> <user-id> <role> [app-
|
|
|
317
436
|
primitive groups memberships <user-id> [app-id] # List user's group memberships
|
|
318
437
|
```
|
|
319
438
|
|
|
439
|
+
**Group resource access:**
|
|
440
|
+
```bash
|
|
441
|
+
primitive groups documents <group-type> <group-id> # List documents a group can access
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
Group permissions on documents are managed via `primitive documents group-permissions` (see [Documents](#documents) above).
|
|
445
|
+
|
|
320
446
|
### Analytics
|
|
321
447
|
|
|
322
448
|
View usage analytics for an app.
|
|
323
449
|
|
|
324
450
|
```bash
|
|
325
|
-
|
|
326
|
-
primitive analytics
|
|
327
|
-
primitive analytics
|
|
328
|
-
primitive analytics
|
|
451
|
+
# Overview & active users
|
|
452
|
+
primitive analytics overview [app-id] # DAU / WAU / MAU + growth
|
|
453
|
+
primitive analytics daily-active [app-id] # Daily active users time series
|
|
454
|
+
primitive analytics rolling-active [app-id] # Rolling active users (28 points)
|
|
455
|
+
primitive analytics cohort-retention [app-id] # Weekly cohort retention matrix
|
|
456
|
+
|
|
457
|
+
# Users
|
|
458
|
+
primitive analytics top-users [app-id] # Most active users
|
|
459
|
+
primitive analytics user-search [app-id] --query <q> # Search by email or ULID
|
|
460
|
+
primitive analytics user-detail <user-ulid> [app-id] # User activity breakdown
|
|
461
|
+
primitive analytics user-snapshot <user-ulid> [app-id] # Latest context snapshot
|
|
462
|
+
|
|
463
|
+
# Events
|
|
464
|
+
primitive analytics events [app-id] # Paginated event feed
|
|
465
|
+
primitive analytics events-grouped [app-id] # Events grouped by dimension
|
|
466
|
+
|
|
467
|
+
# Features
|
|
468
|
+
primitive analytics integrations [app-id] # Integration usage metrics
|
|
469
|
+
primitive analytics workflows [app-id] # Top workflows by runs
|
|
470
|
+
primitive analytics prompts [app-id] # Top prompts by executions
|
|
329
471
|
```
|
|
330
472
|
|
|
331
|
-
**
|
|
332
|
-
- `--window-days <n>` - Time window (default
|
|
333
|
-
- `--limit <n>` - Result limit
|
|
473
|
+
**Common options:**
|
|
474
|
+
- `--window-days <n>` - Time window in days (default varies per command)
|
|
475
|
+
- `--limit <n>` - Result limit (top-users, workflows, prompts)
|
|
476
|
+
- `--group-by <dim>` - Dimension for events-grouped (action, feature, route, country, deviceType, plan, day)
|
|
477
|
+
- `--page <n>` - Page number for events feed (0-based)
|
|
478
|
+
- `--json` - Output raw JSON
|
|
334
479
|
|
|
335
480
|
### Admins (Super-Admin Only)
|
|
336
481
|
|
|
@@ -412,6 +557,9 @@ baseUrl = "https://myapp.com"
|
|
|
412
557
|
googleOAuthEnabled = true
|
|
413
558
|
passkeyEnabled = true
|
|
414
559
|
magicLinkEnabled = false
|
|
560
|
+
otpEnabled = true # email one-time-passcode sign-in
|
|
561
|
+
appleSignInEnabled = true # Sign in with Apple
|
|
562
|
+
appleAudiences = ["com.example.MyApp"] # allowed Apple audiences
|
|
415
563
|
|
|
416
564
|
[cors]
|
|
417
565
|
mode = "custom"
|
|
@@ -419,6 +567,19 @@ allowedOrigins = ["https://myapp.com"]
|
|
|
419
567
|
allowCredentials = true
|
|
420
568
|
```
|
|
421
569
|
|
|
570
|
+
Notes on `[auth]`:
|
|
571
|
+
|
|
572
|
+
- Only keys you actually list are pushed. Omitting a key leaves the server's
|
|
573
|
+
current value untouched — it is **not** reset to `false`. To turn a method
|
|
574
|
+
off, set it explicitly (e.g. `magicLinkEnabled = false`).
|
|
575
|
+
- An unrecognized `[auth]` key (for example a typo like `googleOauthEnabled`)
|
|
576
|
+
produces a warning on `push` and is ignored, rather than being silently
|
|
577
|
+
dropped. The push still applies the recognized keys.
|
|
578
|
+
- `appleAudiences = []` and an omitted `appleAudiences` both mean "no
|
|
579
|
+
audiences" (the server stores them the same way), so `pull` omits the key
|
|
580
|
+
when there are no audiences. A `[] ` round-trip reading back as an omitted
|
|
581
|
+
key is expected, not data loss.
|
|
582
|
+
|
|
422
583
|
### Example: integrations/weather-api.toml
|
|
423
584
|
|
|
424
585
|
```toml
|
|
@@ -475,6 +636,129 @@ primitive apps list
|
|
|
475
636
|
primitive apps list --json | jq '.[0].appId'
|
|
476
637
|
```
|
|
477
638
|
|
|
639
|
+
### Stdout vs. stderr
|
|
640
|
+
|
|
641
|
+
The CLI follows the same convention as `git`, `kubectl`, `aws`, and `gh`:
|
|
642
|
+
|
|
643
|
+
- **stdout** carries the *data* the command produced — JSON documents under
|
|
644
|
+
`--json`, tabular listings (`apps list`), raw values (`primitive token`),
|
|
645
|
+
and the primary `label: value` fields a `get` / `show` / `describe` command
|
|
646
|
+
emits (e.g. `primitive integrations get <id>`).
|
|
647
|
+
- **stderr** carries *diagnostics* — status text (`✓ Created…`,
|
|
648
|
+
`i Waiting for completion...`), warnings (`!` markers), progress lines, and
|
|
649
|
+
the `key: value` summaries shown *after* a side-effecting command runs
|
|
650
|
+
(e.g. the `Webhook ID: …` confirmation printed by `webhooks create`).
|
|
651
|
+
|
|
652
|
+
This means `primitive <cmd> --json | jq` always works, regardless of any
|
|
653
|
+
status / warning / progress text the command may print along the way.
|
|
654
|
+
It also means `primitive integrations get <id> > out.txt` writes the
|
|
655
|
+
integration's fields to `out.txt` while the status diagnostics still appear
|
|
656
|
+
on the terminal via stderr.
|
|
657
|
+
|
|
658
|
+
Conversely, redirecting stderr (`primitive <cmd> 2>/dev/null`) silences
|
|
659
|
+
diagnostics — including success checkmarks like `✓ Pushed 3 changes` — so
|
|
660
|
+
prefer `2>&1 >file.txt` if you want the full transcript.
|
|
661
|
+
|
|
662
|
+
For contributors writing new commands, the output helpers in
|
|
663
|
+
`cli/src/lib/output.ts` make the data-vs-diagnostic split explicit: use
|
|
664
|
+
`json()` and `result(label, value)` for data the caller asked for, and
|
|
665
|
+
`success()` / `info()` / `warn()` / `keyValue()` / `divider()` / `heading()`
|
|
666
|
+
for diagnostics about what the command did.
|
|
667
|
+
|
|
668
|
+
## Programmatic surfaces
|
|
669
|
+
|
|
670
|
+
### `primitive help --json` — command manifest
|
|
671
|
+
|
|
672
|
+
`primitive help --json` prints a machine-readable manifest of the full command
|
|
673
|
+
tree (commands, subcommands, positional args, options, aliases, global options,
|
|
674
|
+
and the CLI version) to **stdout** as a single JSON document, then exits `0`. It
|
|
675
|
+
is hidden/undocumented in human `--help` output, auth-free, and runs entirely
|
|
676
|
+
offline (no project config, no credentials, no network) — so it works in any
|
|
677
|
+
directory, including one with no `.primitive/`.
|
|
678
|
+
|
|
679
|
+
```bash
|
|
680
|
+
primitive help --json | jq '.commands[] | select(.name=="sync") | .commands[].name'
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
Shape (`schemaVersion: 1`):
|
|
684
|
+
|
|
685
|
+
```jsonc
|
|
686
|
+
{
|
|
687
|
+
"schemaVersion": 1,
|
|
688
|
+
"name": "primitive",
|
|
689
|
+
"version": "1.0.49",
|
|
690
|
+
"globalOptions": [ { "flags": "-e, --env <name>", "description": "…", "required": true, "defaultValue": null } ],
|
|
691
|
+
"commands": [
|
|
692
|
+
{
|
|
693
|
+
"name": "sync",
|
|
694
|
+
"description": "…",
|
|
695
|
+
"aliases": [],
|
|
696
|
+
"args": [],
|
|
697
|
+
"options": [],
|
|
698
|
+
"commands": [
|
|
699
|
+
{
|
|
700
|
+
"name": "push",
|
|
701
|
+
"description": "…",
|
|
702
|
+
"aliases": [],
|
|
703
|
+
"args": [ { "name": "app-id", "required": false, "variadic": false, "description": "…" } ],
|
|
704
|
+
"options": [ { "flags": "--dir <path>", "description": "…", "required": true, "defaultValue": null } ],
|
|
705
|
+
"commands": []
|
|
706
|
+
}
|
|
707
|
+
]
|
|
708
|
+
}
|
|
709
|
+
]
|
|
710
|
+
}
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
`schemaVersion` is the contract knob: consumers assert the shape they understand
|
|
714
|
+
and fail loud if a future CLI bumps it (a breaking change for downstream tooling
|
|
715
|
+
such as docs CI that drift-gates documented invocations against the published
|
|
716
|
+
CLI).
|
|
717
|
+
|
|
718
|
+
### `primitive-admin/validators` — TOML validators
|
|
719
|
+
|
|
720
|
+
The TOML validators that `sync push` runs as its load-bearing gate are exported
|
|
721
|
+
from the `primitive-admin/validators` subpath (ESM-only, with types) so external
|
|
722
|
+
tooling can validate exactly the way the published CLI does — instead of
|
|
723
|
+
re-implementing the flow and silently drifting.
|
|
724
|
+
|
|
725
|
+
```ts
|
|
726
|
+
import {
|
|
727
|
+
validateWorkflowTomlSource, // source-level wrapper (parse → expand → validate)
|
|
728
|
+
validateWorkflowToml, // raw: pure fn over already-parsed TOML
|
|
729
|
+
formatWorkflowTomlErrors,
|
|
730
|
+
validateOperations, // raw: pure fn over already-parsed operations[]
|
|
731
|
+
formatIssue,
|
|
732
|
+
} from "primitive-admin/validators";
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
Two contracts:
|
|
736
|
+
|
|
737
|
+
- **`validateWorkflowTomlSource(raw, filePath)`** — pass the **raw TOML source
|
|
738
|
+
string** and the workflow's path. It runs the *identical* parse →
|
|
739
|
+
`expandWorkflowTomlData()` (`include` fragment expansion) → `validateWorkflowToml`
|
|
740
|
+
→ `formatWorkflowTomlErrors` path that `sync push` runs, so it cannot diverge
|
|
741
|
+
from `sync push` on workflow `include` fragments. Returns
|
|
742
|
+
`{ errors, formatted }` (`formatted` is `null` when valid). Fragment files
|
|
743
|
+
resolve relative to `<filePath>/../../workflow-fragments/`, matching the CLI.
|
|
744
|
+
|
|
745
|
+
- **The raw validators** (`validateWorkflowToml`, `validateOperations`,
|
|
746
|
+
`formatWorkflowTomlErrors`, `formatIssue`) are **pure functions over
|
|
747
|
+
already-parsed TOML** — they do *not* read files or parse TOML. The consumer
|
|
748
|
+
parses (e.g. with `@iarna/toml`) and, for workflows, performs any `include`
|
|
749
|
+
expansion itself. There is **no coupling on a specific TOML parser version**:
|
|
750
|
+
pass whatever parsed object / `operations[]` you already have.
|
|
751
|
+
|
|
752
|
+
```ts
|
|
753
|
+
import * as TOML from "@iarna/toml";
|
|
754
|
+
const data = TOML.parse(raw);
|
|
755
|
+
const errs = validateWorkflowToml(data);
|
|
756
|
+
if (errs.length) throw new Error(formatWorkflowTomlErrors(path, errs));
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
Internal helpers (`collectParamRefs`, `declaredParamNames`,
|
|
760
|
+
`locateOperationLine`) are intentionally **not** exported.
|
|
761
|
+
|
|
478
762
|
## Exit Codes
|
|
479
763
|
|
|
480
764
|
- `0` - Success
|
|
@@ -483,12 +767,20 @@ primitive apps list --json | jq '.[0].appId'
|
|
|
483
767
|
|
|
484
768
|
## Environment Variables
|
|
485
769
|
|
|
486
|
-
- `PRIMITIVE_SERVER_URL` - Server URL for login (defaults to `https://primitiveapi.com`)
|
|
770
|
+
- `PRIMITIVE_SERVER_URL` - Server URL for login in legacy mode (defaults to `https://primitiveapi.com`)
|
|
771
|
+
|
|
772
|
+
**Login server resolution:**
|
|
773
|
+
1. Project mode (`.primitive/config.json` present): the active environment's
|
|
774
|
+
`apiUrl`. Select the environment with `-e <name>`, `PRIMITIVE_ENV`, or
|
|
775
|
+
`defaultEnvironment`. An unresolvable environment fails loudly — `login`
|
|
776
|
+
never silently falls back to production.
|
|
777
|
+
2. Legacy mode (no project config): `PRIMITIVE_SERVER_URL`, else the default
|
|
778
|
+
`https://primitiveapi.com`.
|
|
487
779
|
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
780
|
+
> `login` no longer accepts `-s/--server` (removed in a breaking change). Use
|
|
781
|
+
> `-e <env>` in a project, or `PRIMITIVE_SERVER_URL` for local dev / scripts.
|
|
782
|
+
> `init` and `bootstrap` keep their own `-s/--server` (they run before a
|
|
783
|
+
> project config exists).
|
|
492
784
|
|
|
493
785
|
## Development
|
|
494
786
|
|
|
@@ -545,11 +837,13 @@ cli/tests/
|
|
|
545
837
|
config.test.ts # Credentials and config management
|
|
546
838
|
output.test.ts # Output formatting functions
|
|
547
839
|
integration/
|
|
548
|
-
api-client.test.ts
|
|
549
|
-
commands.test.ts
|
|
550
|
-
tokens.test.ts
|
|
551
|
-
databases.test.ts
|
|
552
|
-
|
|
840
|
+
api-client.test.ts # API client HTTP tests
|
|
841
|
+
commands.test.ts # CLI command tests
|
|
842
|
+
tokens.test.ts # Token lifecycle tests
|
|
843
|
+
databases.test.ts # Database CRUD, permissions, group permissions tests
|
|
844
|
+
documents.test.ts # Document group permissions, group resource listing tests
|
|
845
|
+
groups.test.ts # Group CRUD, members, memberships tests
|
|
846
|
+
classroom-e2e.test.ts # End-to-end classroom app workflow (types, rules, operations, access)
|
|
553
847
|
```
|
|
554
848
|
|
|
555
849
|
## Troubleshooting
|