@seliseblocks/cli-os 0.2.3 → 0.2.5

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 (39) hide show
  1. package/AI_USAGE_GUIDE.md +560 -560
  2. package/LICENSE +21 -21
  3. package/README.md +173 -173
  4. package/bin/run.js +2 -2
  5. package/dist/commands/auth/idp/create.d.ts +7 -0
  6. package/dist/commands/auth/idp/create.js +22 -3
  7. package/dist/commands/auth/idp/update.d.ts +7 -0
  8. package/dist/commands/auth/idp/update.js +22 -3
  9. package/dist/commands/new/web.js +4 -0
  10. package/dist/index.js +692 -672
  11. package/dist/lib/scaffold-web/app-core.js +6 -1
  12. package/dist/lib/scaffold-web/blocks-lib.js +36 -2
  13. package/dist/skills/blocks-data-gateway-configuration/SKILL.md +204 -204
  14. package/dist/skills/blocks-data-gateway-crud/SKILL.md +223 -223
  15. package/dist/skills/blocks-data-storage/SKILL.md +253 -253
  16. package/dist/skills/blocks-data-storage/flows/object-management.md +124 -124
  17. package/dist/skills/blocks-frontend-local-https/SKILL.md +100 -100
  18. package/dist/skills/blocks-iam-access-control/SKILL.md +49 -49
  19. package/dist/skills/blocks-iam-access-control/flows/feature-gating.md +38 -38
  20. package/dist/skills/blocks-iam-access-control/flows/manage-roles-permissions.md +110 -110
  21. package/dist/skills/blocks-iam-account/SKILL.md +169 -169
  22. package/dist/skills/blocks-iam-mfa/SKILL.md +124 -124
  23. package/dist/skills/blocks-iam-organizations/SKILL.md +43 -43
  24. package/dist/skills/blocks-iam-organizations/flows/admin-mutations.md +89 -89
  25. package/dist/skills/blocks-iam-organizations/flows/read-and-switch.md +57 -57
  26. package/dist/skills/blocks-iam-sso-oidc-configuration/SKILL.md +105 -89
  27. package/dist/skills/blocks-iam-sso-oidc-implementation/SKILL.md +80 -80
  28. package/dist/skills/blocks-iam-users/SKILL.md +131 -131
  29. package/dist/skills/blocks-localization-configuration/SKILL.md +149 -149
  30. package/dist/skills/blocks-localization-implementation/SKILL.md +63 -63
  31. package/dist/skills/blocks-mail/SKILL.md +95 -95
  32. package/dist/skills/blocks-notification/SKILL.md +69 -69
  33. package/dist/skills/blocks-notifier/SKILL.md +107 -107
  34. package/dist/skills/blocks-onboarding/SKILL.md +78 -78
  35. package/dist/skills/blocks-release-deployment/SKILL.md +81 -81
  36. package/dist/skills/blocks-secrets/SKILL.md +81 -81
  37. package/dist/skills/blocks-storage-configuration/SKILL.md +93 -93
  38. package/dist/skills/lint.mjs +168 -168
  39. package/package.json +47 -47
@@ -80,7 +80,7 @@ export async function writeAppCore(root) {
80
80
  await write(root, "src/app/providers/AuthProvider.tsx", [
81
81
  "import { createContext, useCallback, useContext, useEffect, useMemo, useState } from \"react\";",
82
82
  "import type { ReactNode } from \"react\";",
83
- "import { fetchSessionClaims, logout as endSession, startLogin } from \"../../lib/blocks/auth\";",
83
+ "import { fetchSessionClaims, logout as endSession, onSessionExpired, startLogin } from \"../../lib/blocks/auth\";",
84
84
  "",
85
85
  "type AuthStatus = \"authenticated\" | \"loading\" | \"unauthenticated\";",
86
86
  "",
@@ -129,6 +129,11 @@ export async function writeAppCore(root) {
129
129
  " };",
130
130
  " }, [refresh]);",
131
131
  "",
132
+ " // Fires when a reactive 401 forced a refresh and IAM rejected the refresh",
133
+ " // token outright (invalid_grant) -- blocks/auth.ts already ended the",
134
+ " // session server-side, this just gets the UI to notice and redirect.",
135
+ " useEffect(() => onSessionExpired(() => void refresh()), [refresh]);",
136
+ "",
132
137
  " const login = useCallback(async (returnTo?: string) => {",
133
138
  " await startLogin(returnTo);",
134
139
  " }, []);",
@@ -54,17 +54,22 @@ export async function writeBlocksLib(root) {
54
54
  await write(root, "src/lib/blocks/client.ts", [
55
55
  "import { createBlocksClient } from \"@seliseblocks/client\";",
56
56
  "import { blocksConfig } from \"./config\";",
57
- "import { getValidAccessToken } from \"./auth\";",
57
+ "import { forceRefreshAccessToken, getValidAccessToken } from \"./auth\";",
58
58
  "",
59
59
  "// Single Blocks API entry point for this app -- every Auth, IAM, Data, and",
60
60
  "// Localization call goes through this client, never a hand-written fetch().",
61
61
  "// `accessToken` is a caller-owned resolver: the SDK reads it before each",
62
62
  "// protected call but never stores/refreshes/clears it itself, so the actual",
63
63
  "// session lifecycle (storage, refresh-before-expiry) lives in ./auth.ts.",
64
+ "// `onUnauthorized` is the reactive counterpart: it only fires when a call",
65
+ "// comes back 401 despite a locally-valid-looking token (server-side",
66
+ "// revocation, clock skew), and shares the same in-flight refresh as the",
67
+ "// proactive path so concurrent 401s resolve one refresh, not one each.",
64
68
  "export const blocksClient = createBlocksClient({",
65
69
  " accessToken: () => getValidAccessToken(),",
66
70
  " apiUrl: blocksConfig.apiUrl,",
67
71
  " appDomain: blocksConfig.appDomain,",
72
+ " onUnauthorized: () => forceRefreshAccessToken(),",
68
73
  " oidc: {",
69
74
  " clientId: blocksConfig.oidcClientId,",
70
75
  " scope: blocksConfig.oidcScope,",
@@ -94,6 +99,21 @@ export async function writeBlocksLib(root) {
94
99
  "let cachedRefreshToken: string | undefined;",
95
100
  "let refreshInFlight: Promise<string | undefined> | undefined;",
96
101
  "",
102
+ "// AuthProvider subscribes to this to learn the session died out-of-band (a",
103
+ "// refresh came back invalid_grant) so it can flip status to unauthenticated",
104
+ "// and let RequireAuth redirect to /login -- this module has no router access",
105
+ "// of its own to do that navigation directly.",
106
+ "const sessionExpiredListeners = new Set<() => void>();",
107
+ "",
108
+ "export function onSessionExpired(listener: () => void): () => void {",
109
+ " sessionExpiredListeners.add(listener);",
110
+ " return () => sessionExpiredListeners.delete(listener);",
111
+ "}",
112
+ "",
113
+ "function notifySessionExpired(): void {",
114
+ " for (const listener of sessionExpiredListeners) listener();",
115
+ "}",
116
+ "",
97
117
  "function getAccessToken(): string | undefined {",
98
118
  " if (cachedAccessToken && !isJwtExpired(cachedAccessToken)) return cachedAccessToken;",
99
119
  "",
@@ -137,7 +157,17 @@ export async function writeBlocksLib(root) {
137
157
  "export async function getValidAccessToken(): Promise<string | undefined> {",
138
158
  " const current = getAccessToken();",
139
159
  " if (current) return current;",
160
+ " return forceRefreshAccessToken();",
161
+ "}",
140
162
  "",
163
+ "// Passed to createBlocksClient as `onUnauthorized`: unlike getValidAccessToken,",
164
+ "// this skips the \"is the cached token still fresh\" check and always goes",
165
+ "// straight to refreshAccessToken() -- a 401 means the server already",
166
+ "// disagreed with our local judgment of freshness, so re-checking it would",
167
+ "// just resend the same rejected token. Still funnels through the same",
168
+ "// refreshInFlight guard, so a burst of concurrent 401s (and any proactive",
169
+ "// caller racing them) share one refresh call instead of firing one each.",
170
+ "export async function forceRefreshAccessToken(): Promise<string | undefined> {",
141
171
  " const refreshToken = getRefreshToken();",
142
172
  " if (!refreshToken) return undefined;",
143
173
  "",
@@ -166,8 +196,12 @@ export async function writeBlocksLib(root) {
166
196
  " if (!accessToken) {",
167
197
  " // IAM answered but explicitly rejected the grant (e.g. invalid_grant --",
168
198
  " // the refresh token expired or was already rotated away) -- now it",
169
- " // really is dead, so there is nothing left to retry with.",
199
+ " // really is dead, so this is a full sign-out, not just a cache clear.",
200
+ " // Clear local state before the logout call so its own accessToken",
201
+ " // lookup finds nothing to refresh and doesn't loop back into us.",
170
202
  " clearLocalTokens();",
203
+ " await blocksClient.auth.logout({ refreshToken }).catch(() => undefined);",
204
+ " notifySessionExpired();",
171
205
  " return undefined;",
172
206
  " }",
173
207
  "",
@@ -1,204 +1,204 @@
1
- ---
2
- name: blocks-data-gateway-configuration
3
- description: "Configure a SELISE Blocks project's data model via the blocks CLI — never raw fetch/curl against api.seliseblocks.com. Covers data-source config (data config get/create/update), schema authoring and push (data schema list/pull/push, plus granular get/fields/info commands), data-access policies (data rules pull/deploy/policy), field-level validation rules (data validation *), and reloading so changes go live (data reload, or the composed data sync). Use for defining, editing, securing, validating, or reloading a project's DATA MODEL — schema fields, access policies, and validation rules."
4
- ---
5
-
6
- # Blocks Data — Gateway Configuration
7
-
8
- The Data schema/rules model of a Blocks project is configured entirely through the `blocks` CLI now — there is no supported reason to hand-roll `fetch`/`curl` calls against `api.seliseblocks.com/data/v4` anymore. The CLI reads and writes local files under `blocks/data/` and talks to the Data service for you.
9
-
10
- **Prerequisite:** `blocks init` has been run (creates `blocks/data/schemas/` and `blocks/data/rules.json`) and a project is selected (`blocks use <tenantId>`). If either is missing, or auth state is unknown, run the blocks-onboarding skill first — it covers `auth status` probing, login, and project selection in detail; this skill assumes that's already done.
11
-
12
- ## Check the data-source configuration first
13
-
14
- Before touching schemas, confirm what database actually backs this project's Data Gateway:
15
-
16
- ```bash
17
- blocks data config get --json
18
- ```
19
-
20
- By default every Blocks project runs on **Blocks-managed storage** — most of the time this is the only data-source command you'll ever need, just to confirm it. Only reach for the mutating commands below if the user explicitly wants to point the gateway at their own external database — this is a rare, deliberate action, not a routine step:
21
-
22
- ```bash
23
- blocks data config create --connection-string "<connection string>" --database-name "<name>" --dry-run --json
24
- blocks data config create --connection-string "<connection string>" --database-name "<name>" --yes --json
25
-
26
- blocks data config update --item-id <id> --connection-string "<new connection string>" --dry-run --json
27
- blocks data config update --item-id <id> --connection-string "<new connection string>" --yes --json
28
- ```
29
-
30
- `data config update` also takes `--database-name`, `--collection-name-pattern`, and `--collection-name-editable` (boolean) — use these to rename the target database or adjust how collection names are derived/whether they're editable, on an existing configuration (`--item-id` required either way).
31
-
32
- Treat `--connection-string` as a secret: never print it back unredacted, and don't log it outside the command's own `--dry-run` preview (which redacts it).
33
-
34
- ## Probe first, ask second
35
-
36
- Don't assume the local workspace matches the cloud project. Before editing anything, find out what's actually there:
37
-
38
- ```bash
39
- blocks data schema list --json # what schemas exist in the selected project (read-only)
40
- blocks data schema pull --json # sync them into blocks/data/schemas/*.json locally
41
- blocks data rules pull --json # sync data-access policies into blocks/data/rules.json
42
- ```
43
-
44
- Pulling before editing avoids clobbering schema changes someone else made in the portal or another session.
45
-
46
- ## Workflow: define or edit a schema
47
-
48
- 1. **Pull current state** (above), so local files reflect the project.
49
- 2. **Edit** the relevant JSON file(s) under `blocks/data/schemas/` — add/rename fields, change types, add a new schema file. This is plain file editing; there's no *file-oriented* CLI subcommand for individual field edits (`data schema push` always sends the whole schema), you edit the JSON directly. (`data schema fields` exists as a raw API alternative that adds/updates fields on an existing schema without touching the local file — see "More granular Schema commands" below — but for the local-file workflow described here, just edit the JSON.)
50
- 3. **Validate locally, no API call:**
51
- ```bash
52
- blocks data validate --json
53
- ```
54
- Fix anything it flags before going further — this catches malformed schema/rules JSON before it reaches the network.
55
- 4. **Dry-run the push** to see exactly what would change (create vs. update, which schemas):
56
- ```bash
57
- blocks data schema push --dry-run --json
58
- ```
59
- 5. **Get user approval**, then push for real:
60
- ```bash
61
- blocks data schema push --yes --json
62
- ```
63
- This is mutating — it creates new schemas and updates existing ones in a single call. Never skip straight to `--yes`.
64
- 6. **Reload so it goes live.** Schema/rule edits are staged until reload succeeds — the runtime gateway doesn't see them before this:
65
- ```bash
66
- blocks data reload --dry-run --json
67
- blocks data reload --yes --json
68
- ```
69
-
70
- **Shortcut — recommended default:** steps 3–6 above (validate → schema push → rules deploy → reload) are exactly what `blocks data sync` automates behind a single confirmation:
71
-
72
- ```bash
73
- blocks data sync --dry-run --json
74
- blocks data sync --yes --json
75
- ```
76
-
77
- Reach for `data sync` first unless the user specifically wants to inspect or run one step at a time — it's also the only way to *guarantee* the reload actually happens: nothing else in this CLI calls `data reload` automatically, so a bare `schema push` (or `rules deploy`) without a following `data reload` can leave changes staged but not live. Keep the manual step-by-step above for cases where you want to push schema without touching rules, or need to stop and inspect a dry-run at an individual step.
78
-
79
- ## Workflow: data-access policies / schema security
80
-
81
- Same shape as schemas, in `blocks/data/rules.json`:
82
-
83
- ```bash
84
- blocks data rules pull --json # get current policies locally
85
- # edit blocks/data/rules.json
86
- blocks data validate --json # local-only check
87
- blocks data rules deploy --dry-run --json # preview
88
- blocks data rules deploy --yes --json # apply, after approval
89
- blocks data reload --dry-run --json # then reload so it's live
90
- blocks data reload --yes --json
91
- ```
92
-
93
- **Shortcut:** `blocks data sync --dry-run --json` then `--yes --json` runs validate → schema push → rules deploy → reload together in one confirmed step (see the schema workflow above for the full explanation) — use it instead of the manual deploy+reload above unless you need to run/inspect these steps individually.
94
-
95
- `data rules deploy` applies schema security and data-access policies together — there's no finer-grained CLI split between "field access level" and "policy rule"; both live in `rules.json`.
96
-
97
- For a single policy without touching the rest of `rules.json`, use the granular commands instead of a full pull/edit/deploy round-trip:
98
-
99
- ```bash
100
- blocks data rules policy get <schemaName> --json # read-only, all policies for one schema
101
- blocks data rules policy delete <itemId> --dry-run --json
102
- blocks data rules policy delete <itemId> --yes --json
103
- ```
104
-
105
- There's no single-policy `create`/`update` command — those go through `data rules deploy` (it POSTs new policies and PUTs existing ones from `rules.json`).
106
-
107
- ## Workflow: field-level validation rules
108
-
109
- Data validations are a separate resource from schema field types — a schema field's `type` says *what kind* of value it holds, a validation rule says *what values are acceptable*. There's no file-oriented pull/push for these yet (no `blocks/data/validations.json`); work with them directly:
110
-
111
- ```bash
112
- blocks data validation by-schema <schemaId> --json # everything for one schema
113
- blocks data validation by-schema-field <schemaId> <fieldName> --json # one field's rule
114
- blocks data validation list --schema-id <schemaId> --json # paginated browse
115
- ```
116
-
117
- Create or update a rule (upsert: omit `--item-id` to create, pass it to update). The `validations` array itself has no scalar-flag equivalent — pass it via `--body`/`--file`:
118
-
119
- ```bash
120
- blocks data validation save --schema-id <schemaId> --field-name email \
121
- --body '{"validations":[{"type":1,"value":"^[^@]+@[^@]+\\.[^@]+$","errorMessage":"Enter a valid email","isActive":true}]}' \
122
- --dry-run --json
123
- blocks data validation save --schema-id <schemaId> --field-name email \
124
- --body '{"validations":[{"type":1,"value":"^[^@]+@[^@]+\\.[^@]+$","errorMessage":"Enter a valid email","isActive":true}]}' \
125
- --yes --json
126
-
127
- blocks data validation delete <validationId> --dry-run --json
128
- blocks data validation delete <validationId> --yes --json
129
- ```
130
-
131
- The API doesn't publish named constants for the `type` enum in its schema — if the user needs a specific validation type and you're not sure of its numeric value, run `data validation by-schema-field` on a field with a known-working rule (e.g. one set up in the portal) to see the value in context, rather than guessing.
132
-
133
- ## More granular Schema commands
134
-
135
- `data schema list/pull/push` cover the everyday file-based workflow above. For one-off lookups or advanced schema metadata, these go straight to the API without touching local files:
136
-
137
- ```bash
138
- blocks data schema get <id> --json # single schema by id
139
- blocks data schema get-by-name <schemaName> --json # full field detail by collection name
140
- blocks data schema aggregation --json # schemas + access-level summary (Public/User/Custom x Read/Write/Edit/Delete)
141
- blocks data schema change-logs --json # unadapted change logs; data reload clears these
142
- blocks data schema delete <id> --dry-run --json # irreversible
143
- blocks data schema delete <id> --yes --json
144
- ```
145
-
146
- `data schema info list/save/update` and `data schema fields` are the two-step alternative to `data schema push` (metadata first, fields second) — prefer the file-based `push` workflow above for normal schema authoring; reach for these only if the user specifically wants to add fields to an existing schema without touching its full JSON file, or needs the raw `/schemas/info` metadata-only shape.
147
-
148
- ## `--dry-run` before `--yes` — always
149
-
150
- Every mutating command here (`data config create/update`, `data schema push`, `data schema delete`, `data schema fields`, `data schema info save/update`, `data rules deploy`, `data rules policy delete`, `data validation save/delete`, `data reload`) supports `--dry-run`. Run it, show the user what it says it will do, and only add `--yes` after they approve. This is not optional caution — it's the standard pattern across every `blocks` mutation, not unique to this skill.
151
-
152
- ## What this skill does NOT cover (and why)
153
-
154
- Two things the old, pre-CLI version of this skill used to handle no longer have any supported path — do not paper over the gap by inventing a command or improvising a raw API call:
155
-
156
- - **Mock/sample data cleanup.** There is no `blocks data mock*` command, and the SDK's `data.utilities.mockData()` (in `@seliseblocks/client`) is **read-only** — it inventories mock data, it does not delete it. If a user asks to "wipe the demo data" or "clean up sample records," tell them plainly: this isn't exposed in the current CLI or SDK. Check whether the OS portal (`https://os.seliseblocks.com`) has a Data-section control for it; if not, there's no way to do this today short of deleting real records through generated GraphQL mutations one at a time, which is not the same thing and should not be presented as equivalent.
157
- - **Schema export/import between projects** (e.g. cloning a dev project's data model into staging). No CLI command and no SDK method exist for this. If a user wants to copy a data model between projects, the honest answer is: not supported by current tooling. Check the OS portal for a manual option; otherwise the only fallback is manually recreating schemas in the target project's `blocks/data/schemas/` and pushing them — which is a manual reconstruction, not a real export/import, and should be described as such.
158
-
159
- Don't guess at a raw API call to work around either gap — there is no supported path today, full stop.
160
-
161
- ## The one thing that goes through the SDK, not the CLI
162
-
163
- **AI-generated regex for field validation** is real, but it lives only in `@seliseblocks/client`, not in `blocks`. There's no CLI command for it because it's a single request/response utility call better suited to being scripted inline in app code than wrapped as a terminal command:
164
-
165
- ```ts
166
- import { createBlocksClient } from "@seliseblocks/client";
167
-
168
- const blocks = createBlocksClient({
169
- apiUrl: "https://api.seliseblocks.com",
170
- xBlocksKey: "<project-tenant-id>",
171
- accessToken: () => currentAccessToken
172
- });
173
-
174
- const suggestion = await blocks.data.utilities.generateRegex({
175
- description: "a valid US phone number, digits only, 10 characters"
176
- });
177
- ```
178
-
179
- If a user wants a regex suggestion for a field, write a small one-off script using the SDK like the above rather than trying to shoehorn it into a `blocks` invocation — the CLI genuinely has no equivalent, this isn't an oversight to work around. Once you have the pattern, put it into the relevant field's validation in `blocks/data/schemas/<Schema>.json` and continue with the normal push/reload workflow above.
180
-
181
- ## Gotchas
182
-
183
- - **Reload or it didn't happen.** `data schema push` and `data rules deploy` stage changes; `data reload` is what makes them visible to the runtime gateway (and to any app querying it via `@seliseblocks/client`).
184
- - **Pull before you edit** if you're not sure local files are current — someone may have changed the schema in the portal since your last pull.
185
- - **`data validate` is local-only** — it does not confirm the push will succeed against the server, only that the JSON is well-formed. Still run `--dry-run` on the actual push/deploy/reload commands.
186
- - **Don't invent mock-data-delete or schema-export commands.** They don't exist in the CLI or the SDK today — say so, check the portal, don't fake it with unrelated calls.
187
- - **Never define platform-managed system fields** (`ItemId`, `CreatedDate`, `CreatedBy`, `LastUpdatedDate`, `LastUpdatedBy`, `Language`, `OrganizationId`, `Tags`) in your schema JSON — Blocks adds these to every entity schema automatically.
188
- - **Check `data config get` before assuming Blocks-managed storage.** Most projects use it, but don't state it as fact without checking — and never create/update a data source configuration without explicit user intent, it repoints the project at a different database.
189
- - **`data validation save` requires a `validations` array via `--body`/`--file`.** There's no flag for it — the command errors out with a clear message if it's missing, don't try to work around that by guessing a flag name.
190
-
191
- ## Example trigger prompts
192
-
193
- - "Add an `email` field to my `Customer` schema and push it."
194
- - "Pull the current schemas so I can see what's already defined."
195
- - "Validate my local schema files before I push."
196
- - "Set up a data-access policy so only admins can delete `Order` records."
197
- - "Reload the data schema, I just pushed some field changes."
198
- - "Suggest a regex for validating a postal code field."
199
- - "What database is this project actually using?" → `data config get`.
200
- - "Add a validation rule so the `phone` field only accepts digits." → `data validation save`.
201
- - "What validation rules exist on the `Order` schema?" → `data validation by-schema`.
202
- - "Delete this one data-access policy without touching the rest of my rules file." → `data rules policy delete`.
203
- - "Can you wipe the demo/sample data from my project?" → explain this isn't supported by the CLI or SDK today; point to the portal.
204
- - "Copy my dev project's schemas over to staging." → explain export/import isn't supported by current tooling; point to the portal or manual recreation.
1
+ ---
2
+ name: blocks-data-gateway-configuration
3
+ description: "Configure a SELISE Blocks project's data model via the blocks CLI — never raw fetch/curl against api.seliseblocks.com. Covers data-source config (data config get/create/update), schema authoring and push (data schema list/pull/push, plus granular get/fields/info commands), data-access policies (data rules pull/deploy/policy), field-level validation rules (data validation *), and reloading so changes go live (data reload, or the composed data sync). Use for defining, editing, securing, validating, or reloading a project's DATA MODEL — schema fields, access policies, and validation rules."
4
+ ---
5
+
6
+ # Blocks Data — Gateway Configuration
7
+
8
+ The Data schema/rules model of a Blocks project is configured entirely through the `blocks` CLI now — there is no supported reason to hand-roll `fetch`/`curl` calls against `api.seliseblocks.com/data/v4` anymore. The CLI reads and writes local files under `blocks/data/` and talks to the Data service for you.
9
+
10
+ **Prerequisite:** `blocks init` has been run (creates `blocks/data/schemas/` and `blocks/data/rules.json`) and a project is selected (`blocks use <tenantId>`). If either is missing, or auth state is unknown, run the blocks-onboarding skill first — it covers `auth status` probing, login, and project selection in detail; this skill assumes that's already done.
11
+
12
+ ## Check the data-source configuration first
13
+
14
+ Before touching schemas, confirm what database actually backs this project's Data Gateway:
15
+
16
+ ```bash
17
+ blocks data config get --json
18
+ ```
19
+
20
+ By default every Blocks project runs on **Blocks-managed storage** — most of the time this is the only data-source command you'll ever need, just to confirm it. Only reach for the mutating commands below if the user explicitly wants to point the gateway at their own external database — this is a rare, deliberate action, not a routine step:
21
+
22
+ ```bash
23
+ blocks data config create --connection-string "<connection string>" --database-name "<name>" --dry-run --json
24
+ blocks data config create --connection-string "<connection string>" --database-name "<name>" --yes --json
25
+
26
+ blocks data config update --item-id <id> --connection-string "<new connection string>" --dry-run --json
27
+ blocks data config update --item-id <id> --connection-string "<new connection string>" --yes --json
28
+ ```
29
+
30
+ `data config update` also takes `--database-name`, `--collection-name-pattern`, and `--collection-name-editable` (boolean) — use these to rename the target database or adjust how collection names are derived/whether they're editable, on an existing configuration (`--item-id` required either way).
31
+
32
+ Treat `--connection-string` as a secret: never print it back unredacted, and don't log it outside the command's own `--dry-run` preview (which redacts it).
33
+
34
+ ## Probe first, ask second
35
+
36
+ Don't assume the local workspace matches the cloud project. Before editing anything, find out what's actually there:
37
+
38
+ ```bash
39
+ blocks data schema list --json # what schemas exist in the selected project (read-only)
40
+ blocks data schema pull --json # sync them into blocks/data/schemas/*.json locally
41
+ blocks data rules pull --json # sync data-access policies into blocks/data/rules.json
42
+ ```
43
+
44
+ Pulling before editing avoids clobbering schema changes someone else made in the portal or another session.
45
+
46
+ ## Workflow: define or edit a schema
47
+
48
+ 1. **Pull current state** (above), so local files reflect the project.
49
+ 2. **Edit** the relevant JSON file(s) under `blocks/data/schemas/` — add/rename fields, change types, add a new schema file. This is plain file editing; there's no *file-oriented* CLI subcommand for individual field edits (`data schema push` always sends the whole schema), you edit the JSON directly. (`data schema fields` exists as a raw API alternative that adds/updates fields on an existing schema without touching the local file — see "More granular Schema commands" below — but for the local-file workflow described here, just edit the JSON.)
50
+ 3. **Validate locally, no API call:**
51
+ ```bash
52
+ blocks data validate --json
53
+ ```
54
+ Fix anything it flags before going further — this catches malformed schema/rules JSON before it reaches the network.
55
+ 4. **Dry-run the push** to see exactly what would change (create vs. update, which schemas):
56
+ ```bash
57
+ blocks data schema push --dry-run --json
58
+ ```
59
+ 5. **Get user approval**, then push for real:
60
+ ```bash
61
+ blocks data schema push --yes --json
62
+ ```
63
+ This is mutating — it creates new schemas and updates existing ones in a single call. Never skip straight to `--yes`.
64
+ 6. **Reload so it goes live.** Schema/rule edits are staged until reload succeeds — the runtime gateway doesn't see them before this:
65
+ ```bash
66
+ blocks data reload --dry-run --json
67
+ blocks data reload --yes --json
68
+ ```
69
+
70
+ **Shortcut — recommended default:** steps 3–6 above (validate → schema push → rules deploy → reload) are exactly what `blocks data sync` automates behind a single confirmation:
71
+
72
+ ```bash
73
+ blocks data sync --dry-run --json
74
+ blocks data sync --yes --json
75
+ ```
76
+
77
+ Reach for `data sync` first unless the user specifically wants to inspect or run one step at a time — it's also the only way to *guarantee* the reload actually happens: nothing else in this CLI calls `data reload` automatically, so a bare `schema push` (or `rules deploy`) without a following `data reload` can leave changes staged but not live. Keep the manual step-by-step above for cases where you want to push schema without touching rules, or need to stop and inspect a dry-run at an individual step.
78
+
79
+ ## Workflow: data-access policies / schema security
80
+
81
+ Same shape as schemas, in `blocks/data/rules.json`:
82
+
83
+ ```bash
84
+ blocks data rules pull --json # get current policies locally
85
+ # edit blocks/data/rules.json
86
+ blocks data validate --json # local-only check
87
+ blocks data rules deploy --dry-run --json # preview
88
+ blocks data rules deploy --yes --json # apply, after approval
89
+ blocks data reload --dry-run --json # then reload so it's live
90
+ blocks data reload --yes --json
91
+ ```
92
+
93
+ **Shortcut:** `blocks data sync --dry-run --json` then `--yes --json` runs validate → schema push → rules deploy → reload together in one confirmed step (see the schema workflow above for the full explanation) — use it instead of the manual deploy+reload above unless you need to run/inspect these steps individually.
94
+
95
+ `data rules deploy` applies schema security and data-access policies together — there's no finer-grained CLI split between "field access level" and "policy rule"; both live in `rules.json`.
96
+
97
+ For a single policy without touching the rest of `rules.json`, use the granular commands instead of a full pull/edit/deploy round-trip:
98
+
99
+ ```bash
100
+ blocks data rules policy get <schemaName> --json # read-only, all policies for one schema
101
+ blocks data rules policy delete <itemId> --dry-run --json
102
+ blocks data rules policy delete <itemId> --yes --json
103
+ ```
104
+
105
+ There's no single-policy `create`/`update` command — those go through `data rules deploy` (it POSTs new policies and PUTs existing ones from `rules.json`).
106
+
107
+ ## Workflow: field-level validation rules
108
+
109
+ Data validations are a separate resource from schema field types — a schema field's `type` says *what kind* of value it holds, a validation rule says *what values are acceptable*. There's no file-oriented pull/push for these yet (no `blocks/data/validations.json`); work with them directly:
110
+
111
+ ```bash
112
+ blocks data validation by-schema <schemaId> --json # everything for one schema
113
+ blocks data validation by-schema-field <schemaId> <fieldName> --json # one field's rule
114
+ blocks data validation list --schema-id <schemaId> --json # paginated browse
115
+ ```
116
+
117
+ Create or update a rule (upsert: omit `--item-id` to create, pass it to update). The `validations` array itself has no scalar-flag equivalent — pass it via `--body`/`--file`:
118
+
119
+ ```bash
120
+ blocks data validation save --schema-id <schemaId> --field-name email \
121
+ --body '{"validations":[{"type":1,"value":"^[^@]+@[^@]+\\.[^@]+$","errorMessage":"Enter a valid email","isActive":true}]}' \
122
+ --dry-run --json
123
+ blocks data validation save --schema-id <schemaId> --field-name email \
124
+ --body '{"validations":[{"type":1,"value":"^[^@]+@[^@]+\\.[^@]+$","errorMessage":"Enter a valid email","isActive":true}]}' \
125
+ --yes --json
126
+
127
+ blocks data validation delete <validationId> --dry-run --json
128
+ blocks data validation delete <validationId> --yes --json
129
+ ```
130
+
131
+ The API doesn't publish named constants for the `type` enum in its schema — if the user needs a specific validation type and you're not sure of its numeric value, run `data validation by-schema-field` on a field with a known-working rule (e.g. one set up in the portal) to see the value in context, rather than guessing.
132
+
133
+ ## More granular Schema commands
134
+
135
+ `data schema list/pull/push` cover the everyday file-based workflow above. For one-off lookups or advanced schema metadata, these go straight to the API without touching local files:
136
+
137
+ ```bash
138
+ blocks data schema get <id> --json # single schema by id
139
+ blocks data schema get-by-name <schemaName> --json # full field detail by collection name
140
+ blocks data schema aggregation --json # schemas + access-level summary (Public/User/Custom x Read/Write/Edit/Delete)
141
+ blocks data schema change-logs --json # unadapted change logs; data reload clears these
142
+ blocks data schema delete <id> --dry-run --json # irreversible
143
+ blocks data schema delete <id> --yes --json
144
+ ```
145
+
146
+ `data schema info list/save/update` and `data schema fields` are the two-step alternative to `data schema push` (metadata first, fields second) — prefer the file-based `push` workflow above for normal schema authoring; reach for these only if the user specifically wants to add fields to an existing schema without touching its full JSON file, or needs the raw `/schemas/info` metadata-only shape.
147
+
148
+ ## `--dry-run` before `--yes` — always
149
+
150
+ Every mutating command here (`data config create/update`, `data schema push`, `data schema delete`, `data schema fields`, `data schema info save/update`, `data rules deploy`, `data rules policy delete`, `data validation save/delete`, `data reload`) supports `--dry-run`. Run it, show the user what it says it will do, and only add `--yes` after they approve. This is not optional caution — it's the standard pattern across every `blocks` mutation, not unique to this skill.
151
+
152
+ ## What this skill does NOT cover (and why)
153
+
154
+ Two things the old, pre-CLI version of this skill used to handle no longer have any supported path — do not paper over the gap by inventing a command or improvising a raw API call:
155
+
156
+ - **Mock/sample data cleanup.** There is no `blocks data mock*` command, and the SDK's `data.utilities.mockData()` (in `@seliseblocks/client`) is **read-only** — it inventories mock data, it does not delete it. If a user asks to "wipe the demo data" or "clean up sample records," tell them plainly: this isn't exposed in the current CLI or SDK. Check whether the OS portal (`https://os.seliseblocks.com`) has a Data-section control for it; if not, there's no way to do this today short of deleting real records through generated GraphQL mutations one at a time, which is not the same thing and should not be presented as equivalent.
157
+ - **Schema export/import between projects** (e.g. cloning a dev project's data model into staging). No CLI command and no SDK method exist for this. If a user wants to copy a data model between projects, the honest answer is: not supported by current tooling. Check the OS portal for a manual option; otherwise the only fallback is manually recreating schemas in the target project's `blocks/data/schemas/` and pushing them — which is a manual reconstruction, not a real export/import, and should be described as such.
158
+
159
+ Don't guess at a raw API call to work around either gap — there is no supported path today, full stop.
160
+
161
+ ## The one thing that goes through the SDK, not the CLI
162
+
163
+ **AI-generated regex for field validation** is real, but it lives only in `@seliseblocks/client`, not in `blocks`. There's no CLI command for it because it's a single request/response utility call better suited to being scripted inline in app code than wrapped as a terminal command:
164
+
165
+ ```ts
166
+ import { createBlocksClient } from "@seliseblocks/client";
167
+
168
+ const blocks = createBlocksClient({
169
+ apiUrl: "https://api.seliseblocks.com",
170
+ xBlocksKey: "<project-tenant-id>",
171
+ accessToken: () => currentAccessToken
172
+ });
173
+
174
+ const suggestion = await blocks.data.utilities.generateRegex({
175
+ description: "a valid US phone number, digits only, 10 characters"
176
+ });
177
+ ```
178
+
179
+ If a user wants a regex suggestion for a field, write a small one-off script using the SDK like the above rather than trying to shoehorn it into a `blocks` invocation — the CLI genuinely has no equivalent, this isn't an oversight to work around. Once you have the pattern, put it into the relevant field's validation in `blocks/data/schemas/<Schema>.json` and continue with the normal push/reload workflow above.
180
+
181
+ ## Gotchas
182
+
183
+ - **Reload or it didn't happen.** `data schema push` and `data rules deploy` stage changes; `data reload` is what makes them visible to the runtime gateway (and to any app querying it via `@seliseblocks/client`).
184
+ - **Pull before you edit** if you're not sure local files are current — someone may have changed the schema in the portal since your last pull.
185
+ - **`data validate` is local-only** — it does not confirm the push will succeed against the server, only that the JSON is well-formed. Still run `--dry-run` on the actual push/deploy/reload commands.
186
+ - **Don't invent mock-data-delete or schema-export commands.** They don't exist in the CLI or the SDK today — say so, check the portal, don't fake it with unrelated calls.
187
+ - **Never define platform-managed system fields** (`ItemId`, `CreatedDate`, `CreatedBy`, `LastUpdatedDate`, `LastUpdatedBy`, `Language`, `OrganizationId`, `Tags`) in your schema JSON — Blocks adds these to every entity schema automatically.
188
+ - **Check `data config get` before assuming Blocks-managed storage.** Most projects use it, but don't state it as fact without checking — and never create/update a data source configuration without explicit user intent, it repoints the project at a different database.
189
+ - **`data validation save` requires a `validations` array via `--body`/`--file`.** There's no flag for it — the command errors out with a clear message if it's missing, don't try to work around that by guessing a flag name.
190
+
191
+ ## Example trigger prompts
192
+
193
+ - "Add an `email` field to my `Customer` schema and push it."
194
+ - "Pull the current schemas so I can see what's already defined."
195
+ - "Validate my local schema files before I push."
196
+ - "Set up a data-access policy so only admins can delete `Order` records."
197
+ - "Reload the data schema, I just pushed some field changes."
198
+ - "Suggest a regex for validating a postal code field."
199
+ - "What database is this project actually using?" → `data config get`.
200
+ - "Add a validation rule so the `phone` field only accepts digits." → `data validation save`.
201
+ - "What validation rules exist on the `Order` schema?" → `data validation by-schema`.
202
+ - "Delete this one data-access policy without touching the rest of my rules file." → `data rules policy delete`.
203
+ - "Can you wipe the demo/sample data from my project?" → explain this isn't supported by the CLI or SDK today; point to the portal.
204
+ - "Copy my dev project's schemas over to staging." → explain export/import isn't supported by current tooling; point to the portal or manual recreation.