@microsoft/rayfin-guide 1.35.0-alpha.1287 → 1.35.0-alpha.1331

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.
@@ -149,13 +149,14 @@ Use `--exclude-services <names>` to skip the build/package/deploy phase for supp
149
149
  The runtime settings POST still reflects your `rayfin.yml`, so the backend is never silently reconfigured.
150
150
  The only currently supported value is `staticHosting`; other names fail with a clear error.
151
151
 
152
- The canonical use case is local development where Vite serves the frontend locally, so you want the backend deployed but not the static bundle:
152
+ Use `rayfin dev` for the normal local-development workflow; it never publishes the static bundle.
153
+ The exclude flag remains useful for existing scripts and automation that intentionally run the deployment workflow while Vite serves the frontend:
153
154
 
154
155
  ```bash
155
156
  npx rayfin up --exclude-services staticHosting
156
157
  ```
157
158
 
158
- The samples and templates use this flag in their `npm run dev` script.
159
+ Rayfin's bundled samples and templates use `rayfin dev` for their `npm run dev` script.
159
160
 
160
161
  ## Apply database changes remotely
161
162
 
@@ -202,6 +203,24 @@ Add `--json` for machine-readable output:
202
203
  npx rayfin up status --json
203
204
  ```
204
205
 
206
+ When static content is deployed, the human-readable output includes its public URL:
207
+
208
+ ```text
209
+ Static app: https://silky-sand-4924b3ad1f-centraluseuap.webapp.rayfingwdev.com
210
+ ```
211
+
212
+ The JSON output exposes the same value as `deployment.hostingUrl`:
213
+
214
+ ```json
215
+ {
216
+ "deployment": {
217
+ "hostingUrl": "https://silky-sand-4924b3ad1f-centraluseuap.webapp.rayfingwdev.com"
218
+ }
219
+ }
220
+ ```
221
+
222
+ When no static app URL is recorded, the human-readable output omits the line and `deployment.hostingUrl` is `null` in JSON.
223
+
205
224
  ## Sign out
206
225
 
207
226
  Clear cached credentials when you are done or need to switch accounts:
@@ -273,7 +273,8 @@ Most apps should use `ensureSignedInWithFabric` instead.
273
273
  ## Environment variables
274
274
 
275
275
  Fabric auth requires three Vite environment variables so your frontend can build the `FabricAuthOptions` at runtime.
276
- `npx rayfin up` writes the underlying `RAYFIN_PUBLIC_*` values to `rayfin/.env`, and `rayfin env --framework vite` (run automatically by the scaffolded `predev` / `prebuild` hooks) maps them to Vite-compatible names in `.env.local`.
276
+ `npx rayfin dev` writes the underlying `RAYFIN_PUBLIC_*` values to `rayfin/.env` and maps them to Vite-compatible names in `.env.local` before starting the frontend.
277
+ Production builds retain the scaffolded `prebuild` hook to refresh those values before bundling.
277
278
 
278
279
  | Source variable (`rayfin/.env`) | Vite variable (`.env.local`) | Description | Example |
279
280
  | --- | --- | --- | --- |
@@ -302,7 +303,7 @@ const fabricOptions = {
302
303
 
303
304
  ## Deployment values
304
305
 
305
- After running `npx rayfin up`, the CLI records deployment metadata in `rayfin/.deployments.json` and merges the corresponding `RAYFIN_PUBLIC_*` variables into `rayfin/.env`:
306
+ After running `npx rayfin dev` or `npx rayfin up`, the CLI records deployment metadata in `rayfin/.deployments.json` and merges the corresponding `RAYFIN_PUBLIC_*` variables into `rayfin/.env`:
306
307
 
307
308
  ```text
308
309
  RAYFIN_PUBLIC_ITEM_ID=<guid>
@@ -310,7 +311,8 @@ RAYFIN_PUBLIC_WORKSPACE_ID=<guid>
310
311
  RAYFIN_PUBLIC_PORTAL_URL=https://app.fabric.microsoft.com/
311
312
  ```
312
313
 
313
- Run `rayfin env --framework vite` (or `npm run dev`, which triggers it via the scaffolded `predev` hook) to generate `.env.local` with the Vite-compatible names. Use `RAYFIN_PUBLIC_ITEM_ID` as the `projectId` and `RAYFIN_PUBLIC_WORKSPACE_ID` as the `workspaceId` in your `FabricAuthOptions`.
314
+ `rayfin dev` generates `.env.local` with Vite-compatible names before starting the frontend.
315
+ Use `RAYFIN_PUBLIC_ITEM_ID` as the `projectId` and `RAYFIN_PUBLIC_WORKSPACE_ID` as the `workspaceId` in your `FabricAuthOptions`.
314
316
 
315
317
  ## Troubleshooting
316
318
 
@@ -0,0 +1,78 @@
1
+ ---
2
+ sidebar_position: 2
3
+ ---
4
+
5
+ # connector add
6
+
7
+ ```bash
8
+ npx rayfin connector add --type <type> --workspace-id <ws-id> --item-id <item-id> [--name <name>] [--operations <ops>]
9
+ ```
10
+
11
+ `connector add` declares a connector in `rayfin/rayfin.yml` and scaffolds its supporting files.
12
+
13
+ The CLI verifies the Fabric item, derives a connector `name` from the item's display name (override with `--name`), writes the entry to `rayfin.yml`, scaffolds `rayfin/connectors/<name>/schema.ts`, and runs schema discovery. `rayfin/connectors/<name>/metadata.json` is written so a subset of entities can be generated later.
14
+
15
+ If you do not already know the workspace and item IDs, run [`connector search`](./search.md) first — its `--json` output includes a ready-to-run `addCommand` for each result.
16
+
17
+ ## Options
18
+
19
+ | Flag | Required | Purpose |
20
+ | --------------------- | ------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21
+ | `--type <type>` | yes | The connector type, for example `fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase`, `kusto`, or `fabric-semanticmodel`. |
22
+ | `--workspace-id <id>` | yes (Fabric) | Fabric workspace ID. Must be a literal — `${VAR}` placeholders are rejected. |
23
+ | `--item-id <id>` | yes (Fabric) | Fabric item or artifact ID. Must be a literal. |
24
+ | `--name <name>` | no | Connector name. Derived from the item display name when omitted. |
25
+ | `--operations <ops>` | no | Comma-separated subset of the type's allowed operations, for example `read,update`. Narrows the emitted `operations:` at add time. Omit for all allowed operations. Each value must be in the type's catalog allowlist. |
26
+ | `-y, --yes` | no | Auto-accept overwrite and confirmation prompts (non-interactive). |
27
+ | `-v, --verbose` | no | Verbose diagnostics. |
28
+
29
+ ## Scoping operations
30
+
31
+ Without `--operations`, `connector add` writes **every** operation the catalog allows for the type. Prefer scoping at add time over hand-editing YAML afterwards:
32
+
33
+ ```bash
34
+ npx rayfin connector add --type fabric-warehouse --workspace-id <ws> --item-id <item> --operations read,update
35
+ ```
36
+
37
+ The resulting `rayfin.yml` entry lists operations as objects, not bare strings:
38
+
39
+ ```yaml
40
+ connectors:
41
+ - name: inventory
42
+ type: fabric-warehouse
43
+ config:
44
+ workspaceId: ${WS_ID}
45
+ itemId: ${ITEM_ID}
46
+ auth:
47
+ type: delegated
48
+ operations:
49
+ - name: read
50
+ - name: update
51
+ ```
52
+
53
+ Rules:
54
+
55
+ - You can narrow below the catalog default; you cannot widen above it.
56
+ - There is no `all` meta-operation — list every action explicitly.
57
+ - The host validator rejects unknown or duplicate operation names at `rayfin up` time.
58
+
59
+ ## Category B connectors
60
+
61
+ For `kusto` and `fabric-semanticmodel`, `connector add` writes the `rayfin.yml` entry but there are no GraphQL entities to discover, so no entity files are generated and no row-level security applies:
62
+
63
+ - `executeQuery` is the only allowed operation.
64
+ - `auth.type` must be `delegated`.
65
+ - The connector is pinned to an adapter version.
66
+ - There is no `metadata.json` entity list to generate from.
67
+
68
+ After adding, exercise the connector with [`connector invoke`](./invoke.md) rather than writing entity code.
69
+
70
+ ## Related commands
71
+
72
+ ```bash
73
+ npx rayfin connector list [--verbose] [--json]
74
+
75
+ # Removes the rayfin.yml entry AND the rayfin/connectors/<name>/ directory.
76
+ # Re-add after remove to refresh metadata, then regenerate entity files yourself.
77
+ npx rayfin connector remove <name> [--yes]
78
+ ```
@@ -0,0 +1,58 @@
1
+ ---
2
+ sidebar_position: 6
3
+ ---
4
+
5
+ # Connectors
6
+
7
+ Connectors let a Rayfin app read from — and, for some types, write to — Microsoft Fabric data sources: warehouses, SQL databases, Lakehouse SQL analytics endpoints, semantic models, and KQL databases.
8
+
9
+ ## Prerequisite — the `connector` command group is feature-flagged
10
+
11
+ `rayfin connector ...` is only registered when the `RAYFIN_FEATURE_FLAGS` environment variable contains `connectors`. Without it the commands do not exist and the CLI reports an unknown command.
12
+
13
+ ```bash
14
+ RAYFIN_FEATURE_FLAGS=connectors npx rayfin connector search --help
15
+ ```
16
+
17
+ Each command has its own reference page:
18
+
19
+ - [`connector search`](./search.md) — discover Fabric sources the signed-in identity can add.
20
+ - [`connector add`](./add.md) — declare a connector in `rayfin.yml` and scaffold its files.
21
+ - [`connector inspect`](./inspect.md) — run a single read-only sample query against a source.
22
+ - [`connector invoke`](./invoke.md) — run one named operation against a configured connector.
23
+
24
+ A typical loop is search → add → inspect (Category A) or search → add → invoke (Category B).
25
+
26
+ ## Two categories of connector
27
+
28
+ The commands available to a connector, and the code you write against it, depend on its category.
29
+
30
+ | | Category A — GraphQL entity connectors | Category B — function-bridge connectors |
31
+ | ------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------ |
32
+ | **Types** | `fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase` | `kusto`, `fabric-semanticmodel` |
33
+ | **App surface** | Generated entity files with typed CRUD through the data client | A single `executeQuery` operation carrying a raw query |
34
+ | **Operations** | `read` only for `fabric-sqlanalytics` (Lakehouse SQL endpoints are read-only); `read`, `create`, `update`, `delete` for `fabric-warehouse` and `fabric-sqldatabase` (narrowable) | `executeQuery` only |
35
+ | **Auth** | `delegated` or configured per project | Must be `delegated` |
36
+ | **Entity files and `@role` policies** | Yes | No |
37
+ | **`metadata.json` entities** | Yes | No |
38
+ | **`connector inspect`** | Supported | `fabric-semanticmodel` only — `kusto` is not supported |
39
+ | **`connector invoke`** | Rarely needed | The main way to exercise the connector |
40
+
41
+ Category B connectors are pinned to an adapter version and expose no GraphQL entities, so there is nothing to generate and no row-level security to author.
42
+
43
+ ## Where connector state lives
44
+
45
+ - `rayfin/rayfin.yml` — the `connectors:` block: each connector's `name`, `type`, `config` (workspace and item IDs), `auth`, and `operations`.
46
+ - `rayfin/connectors/<name>/metadata.json` — discovered schema for Category A connectors; the source for generating entity files.
47
+ - `rayfin/connectors/<name>/schema.ts` — placeholder scaffold written by `connector add`.
48
+
49
+ `npx rayfin connector list` prints the configured connectors; `npx rayfin connector remove <name>` deletes both the `rayfin.yml` entry and the `rayfin/connectors/<name>/` directory.
50
+
51
+ ## Deploying connectors
52
+
53
+ ```bash
54
+ npx rayfin up # deploy connectors to the cloud
55
+ npx rayfin up connector apply [--name <name>] # re-apply DAB config only
56
+ ```
57
+
58
+ Most connector commands work before deployment. The exception is [`connector invoke`](./invoke.md) for every type except `fabric-semanticmodel`, which posts to the deployed item and therefore requires a prior `rayfin up`.
@@ -0,0 +1,78 @@
1
+ ---
2
+ sidebar_position: 3
3
+ ---
4
+
5
+ # connector inspect
6
+
7
+ ```bash
8
+ npx rayfin connector inspect (--name <name> | <direct-selector-flags>) (--entity <name> | --query <path>) [--rows <n>] [--verbose] [--json]
9
+ ```
10
+
11
+ `connector inspect` takes no positional arguments — every selector and query mode is a flag.
12
+
13
+ `connector inspect` runs a single read-only sample query against a connector's underlying source, before you have written any app code. Use it to check a table's real data and shape ahead of entity generation, or to debug a row-level-security or query issue on an already-wired connector. It is a development aid — never use it to power app functionality.
14
+
15
+ Supported types: the three Category A SQL types (`fabric-sqlanalytics`, `fabric-warehouse`, `fabric-sqldatabase`) and `fabric-semanticmodel` (DAX). `kusto` is **not** supported today — the command errors with `Unsupported connector type: kusto`.
16
+
17
+ ## Pick exactly one selector and one query mode
18
+
19
+ Two independent choices, each a mutually exclusive pair. Passing zero or both options in a pair fails validation before any network call.
20
+
21
+ | Choice | Option A | Option B |
22
+ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23
+ | **Selector** — which connector or item to query | `--name <name>` — a connector already declared in `rayfin.yml` | Direct mode — `--workspace-id`/`--workspace <name>` plus `--item-id`/`--item <name>` plus `--type <type>`, or `--url <portal-url>` for a semantic model (auto-extracts workspace and item IDs) |
24
+ | **Query mode** | `--entity <name>` — structured: builds `SELECT TOP (n) * FROM <entity>` (SQL) or `EVALUATE TOPN(n, '<entity>')` (DAX) for you | `--query <path>` — raw: runs the literal `.sql` or `.dax` file verbatim, still capped and validated |
25
+
26
+ All four combinations of `{--name, direct} × {--entity, --query}` are valid.
27
+
28
+ `--workspace` and `--item` accept display names and are resolved to IDs the same way [`connector add`](./add.md) fuzzy matching works; `--workspace-id` and `--item-id` take literal IDs directly.
29
+
30
+ ## Entity resolution
31
+
32
+ Applies to `--entity` mode only.
33
+
34
+ - **`--name` plus `--entity` with an unqualified name (no `.`)** — first checked against the connector's local `rayfin/connectors/<name>/metadata.json`, with no network call. Zero matches falls through to live resolution; exactly one match auto-qualifies to `schema.table`; more than one match fails immediately asking you to disambiguate with a schema-qualified name. It does **not** fall through to live resolution in the ambiguous case.
35
+ - **Any other combination** — direct mode, or `--query` mode — never consults `metadata.json`. For SQL types, an unqualified `--entity` is resolved live via `SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE LOWER(TABLE_NAME) = LOWER('<entity>')`: zero matches passes the name through unqualified, one match auto-qualifies, more than one match throws asking you to disambiguate with `--entity <schema>.<table>`.
36
+ - A schema-qualified `--entity <schema>.<table>` skips resolution entirely, in both cases.
37
+
38
+ ## Validation
39
+
40
+ Applies to both query modes.
41
+
42
+ - **SQL** — must start with `SELECT` or `WITH`; must be a single statement (a trailing `;` is fine, an embedded one is not); rejects `INSERT`, `UPDATE`, `DELETE`, `MERGE`, `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `EXEC`/`EXECUTE`, and `INTO` anywhere outside a string literal.
43
+ - **DAX** — must start with `EVALUATE`.
44
+ - `--query <path>` must resolve to a `.sql` or `.dax` file inside the project root; paths outside it are rejected. The project root is the directory containing `rayfin/rayfin.yml` when one is found. Direct mode (no `--name`) falls back to the current working directory if no `rayfin.yml` exists, so `--query` never requires a Rayfin project.
45
+ - `--rows <n>` caps the sample size — default 10, maximum 100. The result reports `truncated: true` when the source had more rows than the cap.
46
+
47
+ ## Examples
48
+
49
+ ```bash
50
+ # --name selector + structured entity mode
51
+ npx rayfin connector inspect --name inventory --entity Order
52
+
53
+ # --name selector + raw query file
54
+ npx rayfin connector inspect --name inventory --query rayfin/queries/order.sql
55
+
56
+ # Direct selector (literal IDs) + structured entity mode
57
+ npx rayfin connector inspect --workspace-id <ws-id> --item-id <item-id> --type fabric-warehouse --entity Order
58
+
59
+ # Direct selector (fuzzy display names) + raw query file
60
+ npx rayfin connector inspect --workspace "Sales Analytics" --item "Inventory Warehouse" --type fabric-warehouse --query rayfin/queries/order.sql
61
+
62
+ # Semantic model (DAX), resolved from a Fabric portal URL
63
+ npx rayfin connector inspect --url <fabric-portal-semantic-model-url> --query rayfin/queries/model.dax
64
+ ```
65
+
66
+ Combine `--workspace-id`, `--item-id`, and `--type` with either `--entity` or `--query` freely — none of the four combinations require `--name` or a `rayfin.yml` entry to exist.
67
+
68
+ ## Errors
69
+
70
+ SQL errors are categorized before being shown:
71
+
72
+ | Condition | Surfaced as |
73
+ | -------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
74
+ | SQL Server error `229`, `230`, `262`, `297`, `300` | "Permission denied", with a permissions recovery hint. |
75
+ | SQL Server error `18456`, `4060`, or `ELOGIN` | "Authentication failed", with a `rayfin login` recovery hint. |
76
+ | Anything else, including invalid object name / table not found | The underlying message, with a generic "verify the entity/table name and access" hint. |
77
+
78
+ Semantic model HTTP errors map `401` to re-login, `403` to permissions, and everything else to the generic hint.
@@ -0,0 +1,76 @@
1
+ ---
2
+ sidebar_position: 4
3
+ ---
4
+
5
+ # connector invoke
6
+
7
+ ```bash
8
+ npx rayfin connector invoke <connector-name> <operation> (--input '<json>' | --file <path>) [--verbose] [--json]
9
+ ```
10
+
11
+ `connector invoke` runs a single named operation against a configured connector and prints the result. It is the loop for exercising [Category B connectors](./index.md#two-categories-of-connector) — `executeQuery` over DAX or KQL — without writing any app code.
12
+
13
+ Both positionals also have flag forms, `--name <name>` and `--operation <operation>`, which win over the positionals when both are given.
14
+
15
+ Run it from inside a Rayfin project: it resolves `rayfin/rayfin.yml`, and fails with a recovery hint if there is no project root or the `connectors:` block is empty.
16
+
17
+ ## Payload input
18
+
19
+ Exactly one of these is required — passing both, or neither, fails:
20
+
21
+ - `--input '<json>'` — inline JSON payload for the operation input.
22
+ - `--file <path>` — path to a JSON file. The path is resolved against the project root, and **the resolved path must stay inside it**; a `../` escape is rejected before the file is read. An absolute path is accepted as long as it resolves inside the project root.
23
+
24
+ ## Operation resolution
25
+
26
+ The requested operation is matched **case-insensitively** against the connector's `operations:` list in `rayfin.yml`. If that entry has no `operations:`, the connector type's full catalog allowlist is used instead. A miss fails with the allowed set listed.
27
+
28
+ ## Transports
29
+
30
+ Two transports, chosen by connector type:
31
+
32
+ - **`fabric-semanticmodel`** — the CLI calls Fabric/Power BI **directly under the developer's own identity**, so this works whether or not `npx rayfin up` has been run. It requires `workspaceId` **and** `itemId` under the connector's `config:` block; without both, it fails up front rather than falling through to the deployed transport. The Power BI scope and audience are derived from the configured Fabric API base URL, so an INT ring mints an INT-audience token.
33
+ - **Every other type, including `kusto`** — POSTs to the deployed item at `<remote-endpoint>/__private/connectors/<name>/invoke`, so it requires a prior `npx rayfin up`.
34
+
35
+ ## Token handling (semantic model path)
36
+
37
+ `npx rayfin login` only consents to the Fabric scope, not the Power BI scope this path needs. Consequences:
38
+
39
+ - Interactively (no `--json`), the CLI prompts to complete Power BI consent.
40
+ - With `--json`, token acquisition is **silent-only** so prompts cannot corrupt the single-JSON-object contract. If consent is still needed the command fails and tells you to drop `--json` or set `RAYFIN_TOKEN`.
41
+ - `RAYFIN_TOKEN`, when set, is passed through **unchanged** regardless of the scopes requested. Its audience is decoded and checked locally, so a wrong-audience or undecodable token fails with a clear message instead of surfacing later as a phantom workspace-permission error.
42
+
43
+ ## Output
44
+
45
+ `--verbose` cannot be combined with `--json` — narration would break the single-object contract.
46
+
47
+ Success emits `{status: 'ok', connector, operation, output}`. In non-JSON modes it prints `✅ Invoked <name>.<operation>` followed by the output.
48
+
49
+ What `output` holds depends on the connector. `fabric-semanticmodel` normalises inside its `invoke` middleware, so `output` is already a discriminated result rather than the raw service envelope: `{status: 'success', table, requestId}`, where `table.columns` are `{name, dataType}` and `table.rows` are column-aligned arrays. No caller-side conversion is needed, and the same shape comes back whether the operation ran locally or through the deployed item.
50
+
51
+ A resolved call is **not** automatically a success, and the failure signal depends on the same distinction. A connector that normalises reports Power BI failures — expired token, missing Build permission, throttling — as `{status: 'error', error, requestId}`, where `error` carries `category`, `message`, and optional `code` and `details`. A connector that returns the raw envelope reports failure as `status: 'Failed'` instead. The CLI reads both, converts either into a non-zero exit, and surfaces the service-supplied request id for tracing.
52
+
53
+ ## Examples
54
+
55
+ ```bash
56
+ # Inline payload, positional args
57
+ npx rayfin connector invoke mymodel executeQuery --input '{"query":"EVALUATE TOPN(10, Sales)"}'
58
+
59
+ # Same thing with flag forms and a payload file
60
+ npx rayfin connector invoke --name mymodel --operation executeQuery --file ./payload.json
61
+
62
+ # Machine-readable (no --verbose allowed alongside)
63
+ npx rayfin connector invoke mymodel executeQuery --input '{"query":"EVALUATE TOPN(1, Sales)"}' --json
64
+ ```
65
+
66
+ ## Errors
67
+
68
+ | Message | Fix |
69
+ | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
70
+ | `Missing required connector invoke arguments` | Supply both the connector name and the operation. |
71
+ | `Choose exactly one payload source` / `Missing payload input` | Pass exactly one of `--input` or `--file`. |
72
+ | `Input file must be inside the project` | Use a relative path under the project root. |
73
+ | `Operation "<op>" is not allowed for connector "<name>"` | Check the connector's `operations:` in `rayfin.yml`, or the type's allowlist. |
74
+ | `missing workspaceId/itemId in rayfin.yml` | Add both under `config:`, or re-run [`connector add`](./add.md). |
75
+ | `Access token has the wrong audience for the Power BI query API` | Unset or replace `RAYFIN_TOKEN`, or re-run without `--json` to consent interactively. |
76
+ | `No remote endpoint configured` | The non-semantic-model transport needs a deployed item — run `npx rayfin up` first. |
@@ -0,0 +1,66 @@
1
+ ---
2
+ sidebar_position: 1
3
+ ---
4
+
5
+ # connector search
6
+
7
+ ```bash
8
+ npx rayfin connector search [query] [--workspace-id <id> --type <types> | --all-workspaces --type <types>] [--limit <n>] [--json]
9
+ ```
10
+
11
+ `connector search` finds Fabric data sources — warehouses, SQL databases, Lakehouses, semantic models, and KQL databases — that the signed-in identity can add as connectors, before you know exact workspace or item IDs.
12
+
13
+ Use it to find candidates for [`connector add`](./add.md). It never touches app data itself.
14
+
15
+ ## Scope resolution
16
+
17
+ The search scope is resolved in priority order:
18
+
19
+ 1. `--workspace-id <id>` — search exactly one workspace. **Requires** `--type`: without it, every discoverable item type would be fetched with a separate request to that workspace.
20
+ 2. `--all-workspaces` — tenant-wide scan across every workspace the identity can access. **Requires** `--type` (the only server-side filter) to keep the scan bounded.
21
+ 3. No scope flag, run inside a Rayfin project with deployments — defaults to the union of every workspace recorded in the project's deployments registry (dev, prod, and so on), without switching the active deployment. This is the only scope that does **not** require `--type`.
22
+
23
+ Only one of `--workspace-id` and `--all-workspaces` may be given. Outside a Rayfin project with zero deployments, one of them is required; omitting both fails with `workspace scope is required`.
24
+
25
+ ## Filtering
26
+
27
+ | Flag | Purpose |
28
+ | ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
29
+ | `[query]` (positional) or `--query <text>` | Case-insensitive name filter. Omit to list every connectable source in scope. `--query` wins if both are given. |
30
+ | `--type <types>` | Comma-separated subset of connector types, for example `fabric-warehouse,fabric-sqldatabase`. Required with `--workspace-id` and with `--all-workspaces`. |
31
+ | `--limit <n>` | Caps the rows shown. Ignored in interactive mode, where the picker paginates the full result set instead; applies only to plain and `--json` output. |
32
+
33
+ ## Output modes
34
+
35
+ - **Interactive** (default on a TTY) — a paginated picker. Page size comes from `RAYFIN_CONNECTOR_SEARCH_PAGE_SIZE`, default 30. Picking a source runs a pre-flight access check (SQL endpoint, Kusto endpoint, or semantic model probe, depending on type) before handing off to [`connector add`](./add.md); a failed check re-shows the picker instead of aborting. `--yes` and `--verbose` are forwarded to the `connector add` it runs.
36
+ - **Plain** (non-TTY) — prints the list and exits, with no prompt.
37
+ - **`--json`** — a machine-readable envelope on stdout: `{status, query, scope, count, sources}`. Each row carries `workspaceId`, `itemId`, and `connectorType`, plus `suggestedName` (the sanitized display name to use as the connector name) and `addCommand` (the exact `rayfin connector add …` string to run). Skips both the picker and the access-check pre-flight.
38
+
39
+ Duplicate-looking entries — for example a SQL Database and its SQL-analytics-endpoint twin sharing a workspace and display name — are grouped visually next to each other in interactive and plain output only. They are never deduplicated, and `--json` always returns the canonical, ungrouped order.
40
+
41
+ The SQL-endpoint-permissions note ("Schema discovery for SQL-based connectors requires SQL endpoint permissions") only prints when at least one result is a SQL-dialect connector type — never for a semantic-model-only or Kusto-only result set.
42
+
43
+ ## Examples
44
+
45
+ ```bash
46
+ # Query text as a positional argument, scoped to one workspace (--type is required with --workspace-id)
47
+ npx rayfin connector search "sales" --workspace-id <ws-id> --type fabric-warehouse
48
+
49
+ # Tenant-wide scan, narrowed to one or more types (--type is required with --all-workspaces)
50
+ npx rayfin connector search --all-workspaces --type fabric-warehouse,fabric-sqldatabase
51
+
52
+ # No scope flag inside a deployed project — searches every deployment workspace, no --type needed
53
+ npx rayfin connector search
54
+
55
+ # Machine-readable output, capped to 5 rows, skips the interactive picker
56
+ npx rayfin connector search --workspace-id <ws-id> --type fabric-warehouse --json --limit 5
57
+ ```
58
+
59
+ ## Errors
60
+
61
+ | Message | Fix |
62
+ | ---------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
63
+ | `Command incomplete: workspace scope is required` | No `--workspace-id` or `--all-workspaces` and no deployments found. Pass one of those flags. |
64
+ | `--type is required with --all-workspaces` | Add a `--type` filter to bound the tenant-wide scan. |
65
+ | `--type is required with --workspace-id` | Add a `--type` filter so a single request is made instead of one per discoverable item type. |
66
+ | `You don't have the required permission on <source>` | The pre-flight access check failed during the interactive add handoff. Pick a different source or request access. |
@@ -10,8 +10,9 @@ The `rayfin env` command (or the auto-emit built into `rayfin up`) maps them to
10
10
 
11
11
  | Variable | Description | Populated by |
12
12
  | --- | --- | --- |
13
- | `RAYFIN_PUBLIC_API_URL` | Rayfin backend URL (`http://localhost:5168` for local dev). | `rayfin up` |
14
- | `RAYFIN_PUBLIC_PUBLISHABLE_KEY` | Public key for Rayfin SDK initialization. | `rayfin up` |
13
+ | `RAYFIN_PUBLIC_API_URL` | Rayfin backend URL selected for the development or deployed environment. | `rayfin dev` / `rayfin up` |
14
+ | `RAYFIN_PUBLIC_PUBLISHABLE_KEY` | Public key for Rayfin SDK initialization. | `rayfin dev` / `rayfin up` |
15
+ | `RAYFIN_PUBLIC_FUNCTIONS_URL` | URL of the local Functions host started by `rayfin dev`. Removed when functions are disabled so local clients do not retain a stale host. | `rayfin dev` |
15
16
  | `RAYFIN_PUBLIC_ITEM_ID` | Fabric AppBackend item ID. Used for Fabric brokered auth. | `rayfin up` |
16
17
  | `RAYFIN_PUBLIC_WORKSPACE_ID` | Fabric workspace ID. Used for Fabric brokered auth. | `rayfin up` |
17
18
  | `RAYFIN_PUBLIC_TENANT_ID` | Entra ID tenant for workspace disambiguation. | `rayfin up` |
@@ -27,6 +28,7 @@ The `rayfin env` command (or the auto-emit built into `rayfin up`) maps them to
27
28
  | --- | --- | --- | --- |
28
29
  | `RAYFIN_PUBLIC_API_URL` | `VITE_RAYFIN_API_URL` | `NEXT_PUBLIC_RAYFIN_API_URL` | `API_URL` |
29
30
  | `RAYFIN_PUBLIC_PUBLISHABLE_KEY` | `VITE_RAYFIN_PUBLISHABLE_KEY` | `NEXT_PUBLIC_RAYFIN_PUBLISHABLE_KEY` | `PUBLISHABLE_KEY` |
31
+ | `RAYFIN_PUBLIC_FUNCTIONS_URL` | `VITE_RAYFIN_FUNCTIONS_URL` | `NEXT_PUBLIC_RAYFIN_FUNCTIONS_URL` | `FUNCTIONS_URL` |
30
32
  | `RAYFIN_PUBLIC_ITEM_ID` | `VITE_FABRIC_ITEM_ID` | `NEXT_PUBLIC_FABRIC_ITEM_ID` | `ITEM_ID` |
31
33
  | `RAYFIN_PUBLIC_WORKSPACE_ID` | `VITE_FABRIC_WORKSPACE_ID` | `NEXT_PUBLIC_FABRIC_WORKSPACE_ID` | `WORKSPACE_ID` |
32
34
  | `RAYFIN_PUBLIC_TENANT_ID` | `VITE_FABRIC_TENANT_ID` | `NEXT_PUBLIC_FABRIC_TENANT_ID` | `TENANT_ID` |
@@ -40,6 +42,37 @@ Custom `RAYFIN_PUBLIC_*` variables you add follow a generic pattern: `RAYFIN_PUB
40
42
  The sample `vite.config.ts` files pin the server to it with `strictPort`, so if the assigned port is already taken the dev server fails fast instead of silently drifting to another port.
41
43
  To run on a different port, set `RAYFIN_PUBLIC_FRONTEND_PORT` in `rayfin/.env` (then re-run `rayfin env`); `rayfin up` registers whatever value is assigned in the deployed redirect allow-list.
42
44
 
45
+ ### Bare development runtime wiring
46
+
47
+ `npx rayfin dev` runs the local frontend against the Fabric backend by default.
48
+ Use `npx rayfin dev --provider fabric` to select the same provider explicitly.
49
+ The CLI reuses a registered deployment or provisions and records a missing AppBackend.
50
+ Set `RAYFIN_WORKSPACE_ID` to target a specific workspace; otherwise the active registered deployment or My workspace is used.
51
+
52
+ The CLI starts `npm run dev:frontend` when that script exists and falls back to `npm run dev` for existing projects.
53
+ This lets bundled templates expose `npm run dev` as the complete session without recursively starting the CLI.
54
+ When migrating an existing project to `"dev": "rayfin dev"`, also add a non-recursive child such as `"dev:frontend": "vite"`; otherwise the CLI fails with an actionable recursion error.
55
+ Scripts are resolved from `services.staticHosting.path` when configured, otherwise from the project root.
56
+ For a nested frontend package, declare `dev:frontend` (or the legacy `dev` fallback) in that package's `package.json`.
57
+
58
+ When `services.functions.enabled` is `true`, the same command builds and starts the configured functions package with Azure Functions Core Tools.
59
+ The CLI reserves the nearest available Functions port starting at `7071` and writes its URL to `RAYFIN_PUBLIC_FUNCTIONS_URL` before starting the frontend.
60
+ When functions are disabled, the CLI removes any stale `RAYFIN_PUBLIC_FUNCTIONS_URL` from `rayfin/.env` and regenerates the framework environment file without it.
61
+
62
+ The local functions setup makes these workspace changes:
63
+
64
+ - Merges backend coordinates and the Node inspector argument into the configured functions package's `local.settings.json`.
65
+ - Adds a `Functions: Attach` configuration to the root `.vscode/launch.json` after the Functions host becomes ready.
66
+ - Leaves JSON-with-comments launch files unchanged and reports that the attach configuration must be added manually.
67
+ - Patches recognized `src/services/rayfinClient.ts` and `src/services/bootstrap.ts` template files once so `functionsBaseUrl` reads `VITE_RAYFIN_FUNCTIONS_URL`.
68
+ - Regenerates the framework `.env.local` file unless `--no-emit-env` is set.
69
+
70
+ The Node inspector defaults to port `9229` and slides to the nearest available port when needed.
71
+ Use the `Functions: Attach` launch configuration after the host is ready to debug local function code.
72
+
73
+ To run the managed backend locally instead, enable the Docker preview and use `npx rayfin dev --provider docker`.
74
+ Frontend and functions code still run as local processes; only the managed Rayfin backend moves from Fabric to Docker.
75
+
43
76
  ## Tooling overrides
44
77
 
45
78
  These variables configure CLI and extension behavior.
@@ -146,14 +179,15 @@ These variables are read from the shell environment and are never written to fil
146
179
  | `RAYFIN_WORKSPACE_ID` | Fabric workspace ID for non-interactive setup. Used with `RAYFIN_TOKEN`. |
147
180
  | `RAYFIN_TENANT_ID` | Entra ID tenant used by `rayfin up` for portal URLs and the `ctid` query parameter. Equivalent to the `-t, --tenant <id>` flag (precedence: flag > env var > signed-in tenant). |
148
181
  | `RAYFIN_ENCRYPTION_FALLBACK_ENABLED` | Set to `true` to allow plaintext token cache on systems without OS credential storage. Development only. |
149
- | `RAYFIN_FEATURE_FLAGS` | Comma-separated list of experimental feature names to enable (case-insensitive). Recognized values include `storage`, `functions`, and `postgresql`. |
150
- | `RAYFIN_WEBSERVICE_IMAGE_NAME` | **Experimental.** Override the webservice container image used by `rayfin dev` and `docker compose`. Both `rayfin dev` and this variable are experimental and may change. Defaults to `ghcr.io/microsoft/project-rayfin/webservice:cli-<version>`. |
182
+ | `RAYFIN_FEATURE_FLAGS` | Comma-separated list of experimental feature names to enable (case-insensitive). Recognized values include `docker-local-dev`, `storage`, `functions`, and `postgresql`. |
183
+ | `RAYFIN_WEBSERVICE_IMAGE_NAME` | **Experimental.** Override the webservice container image used by `rayfin dev --provider docker` and Docker Compose. Defaults to `ghcr.io/microsoft/project-rayfin/webservice:cli-<version>`. |
151
184
  | `RAYFIN_APPINSIGHTS_CONNECTION_STRING` | Override the telemetry endpoint for the CLI and VS Code extension. |
152
185
 
153
186
  ### Recognized `RAYFIN_FEATURE_FLAGS` values
154
187
 
155
188
  | Flag | Effect |
156
189
  | --- | --- |
190
+ | `docker-local-dev` | Allows `rayfin dev --provider docker` and the Docker maintenance commands. Bare `rayfin dev` remains available without this flag and defaults to Fabric. |
157
191
  | `storage` | Exposes storage commands (`rayfin dev storage *`) and storage prompts during `rayfin init`. |
158
192
  | `functions` | Exposes Functions service prompts during `rayfin init`. |
159
193
  | `postgresql` | Adds PostgreSQL as a selectable dialect during `rayfin init` and `rayfin init` with bundled templates. |
@@ -16,10 +16,12 @@ see [CLI Installation](./installation.md).
16
16
  ```bash
17
17
  npm create @microsoft/rayfin@latest my-app # 1. Create a project from a template
18
18
  cd my-app
19
- npx rayfin up # 2. Start backend services
20
- npm run dev # 3. Run the frontend dev server
19
+ npm run dev # 2. Start the complete development session
21
20
  ```
22
21
 
22
+ The scaffolded `dev` script runs `rayfin dev`.
23
+ It provisions or reuses a Fabric backend, applies the declared services and schema, and starts the frontend and enabled Functions locally.
24
+
23
25
  > **Existing or empty projects:** Use `npx rayfin init` instead of `npm create` to add Rayfin to a project that already has source code or an empty directory.
24
26
  > The init command walks you through enabling services, choosing a database dialect, and configuring static hosting without scaffolding a new template.
25
27
 
@@ -41,6 +43,13 @@ For the full walkthrough, see the [CLI Quickstart](./quickstart.md) or the [Buil
41
43
  > Use this to enable or disable services, switch the database dialect, or toggle static hosting without editing `rayfin.yml` by hand.
42
44
  > The CLI preserves your data model files under `rayfin/data/` during reconfiguration.
43
45
 
46
+ ### Development
47
+
48
+ | Command | Description |
49
+ | --- | --- |
50
+ | `npx rayfin dev` | Start the development session. Uses the Fabric backend provider by default, provisions a missing AppBackend, applies declared state, and starts frontend and Functions code locally. |
51
+ | `npx rayfin dev --provider docker` | Run the managed backend through the preview Docker provider while keeping frontend and Functions code local. |
52
+
44
53
  ### Deployment
45
54
 
46
55
  | Command | Description |
@@ -55,6 +64,20 @@ For the full walkthrough, see the [CLI Quickstart](./quickstart.md) or the [Buil
55
64
  | `npx rayfin up secrets apply` | Read secrets from `rayfin/.env` file (prefixed with `RAYFIN_SECRET_`) and securely apply them to the remote Rayfin item workload. Validates that secrets are persisted. Use `--env-file <path>` to specify a custom .env file location. |
56
65
  | `npx rayfin up staticapp deploy` | Build, package, and deploy static content to the remote Rayfin item. Add `--skip-build` to deploy existing build output without rebuilding. |
57
66
 
67
+ ### Connectors
68
+
69
+ Connectors let a Rayfin app read from existing Fabric sources. The `connector` command group is only registered when `RAYFIN_FEATURE_FLAGS` contains `connectors`. See [Connectors](./connectors/index.md) for the full guide.
70
+
71
+ | Command | Description |
72
+ | --- | --- |
73
+ | `npx rayfin connector search [query]` | Discover Fabric sources you can connect to. See [Searching for sources](./connectors/search.md). |
74
+ | `npx rayfin connector add` | Declare a connector in `rayfin.yml` and run schema discovery. See [Adding a connector](./connectors/add.md). |
75
+ | `npx rayfin connector list` | List the connectors declared in the current project. |
76
+ | `npx rayfin connector remove <name>` | Remove a connector's `rayfin.yml` entry and its `rayfin/connectors/<name>/` directory. |
77
+ | `npx rayfin connector inspect` | Run a read-only sample query against a connector's source. See [Inspecting a source](./connectors/inspect.md). |
78
+ | `npx rayfin connector invoke <name> <operation>` | Run one named operation against a configured connector. See [Invoking an operation](./connectors/invoke.md). |
79
+ | `npx rayfin up connector apply` | Re-apply connector configuration to the remote Rayfin item. |
80
+
58
81
  ## Update the CLI
59
82
 
60
83
  To get the latest version of the Rayfin CLI and its dependencies:
@@ -60,15 +60,14 @@ npx rayfin --help
60
60
 
61
61
  ## First steps
62
62
 
63
- Start the backend services:
63
+ Start the complete development session:
64
64
 
65
65
  ```bash
66
- npx rayfin up
66
+ npm run dev
67
67
  ```
68
68
 
69
- This launches the enabled services,
70
- runs health checks, and applies the database configuration.
71
- Wait for the deployment to complete before continuing.
69
+ The bundled templates' script runs `rayfin dev`.
70
+ It provisions or reuses the Fabric backend, applies declared state, generates framework environment variables, and starts the frontend and enabled Functions locally.
72
71
 
73
72
  Apply schema changes after updating your data models:
74
73
 
@@ -76,12 +75,6 @@ Apply schema changes after updating your data models:
76
75
  npx rayfin up db apply
77
76
  ```
78
77
 
79
- Run your frontend dev server in a separate terminal:
80
-
81
- ```bash
82
- npm run dev
83
- ```
84
-
85
78
  ## Update the CLI
86
79
 
87
80
  To get the latest version:
@@ -34,6 +34,19 @@ npx rayfin init
34
34
 
35
35
  This installs the CLI and runs the interactive setup to create the `rayfin/` directory with starter configuration files.
36
36
 
37
+ ## Develop locally
38
+
39
+ ```bash
40
+ npx rayfin dev
41
+ ```
42
+
43
+ - Uses the Fabric backend provider by default and provisions a missing AppBackend.
44
+ - Applies runtime settings and database schema before starting user code.
45
+ - Starts the frontend and enabled Functions as local processes.
46
+ - Press `Ctrl+C` to end the session.
47
+
48
+ Bundled templates expose the same workflow as `npm run dev`.
49
+
37
50
  ## Deploy to Fabric
38
51
 
39
52
  ```bash
@@ -69,8 +82,9 @@ npx rayfin up db apply [--force]
69
82
 
70
83
  If `staticHosting` is enabled in `rayfin/rayfin.yml`, `npx rayfin up` automatically builds, packages, and deploys your static assets.
71
84
 
72
- When iterating locally with Vite, opt out of the static deploy phase with `npx rayfin up --exclude-services staticHosting`.
73
- This is what the scaffolded `npm run dev` script does so the backend deploys but the local Vite server keeps serving your frontend.
85
+ `rayfin dev` never publishes static content, so Vite can serve the frontend without a static deployment.
86
+
87
+ The lower-level `npx rayfin up --exclude-services staticHosting` command remains available for existing scripts and automation that need to run the deployment workflow while skipping only static content.
74
88
 
75
89
  To redeploy static content independently without running the full `rayfin up` flow:
76
90
 
@@ -26,7 +26,7 @@ Apply `@role` at the class level to control which roles can perform which action
26
26
  | --- | --- |
27
27
  | `roleName` | The role name (`'anonymous'` or `'authenticated'`). |
28
28
  | `actions` | A single action or array of actions: `'create'`, `'read'`, `'update'`, `'delete'`, or `'*'` for all. |
29
- | `options` | Optional object with `check`, `include`, and `exclude` properties. |
29
+ | `options` | Optional object with `policy`, `include`, and `exclude` properties. |
30
30
 
31
31
  ## Basic example
32
32
 
@@ -38,7 +38,7 @@ import { entity, role, uuid, text } from '@microsoft/rayfin-core';
38
38
  @entity()
39
39
  @role('anonymous', 'read')
40
40
  @role('authenticated', ['create', 'read', 'update', 'delete'], {
41
- check: (claims, item) => claims.sub.eq(item.user_id),
41
+ policy: (claims, item) => claims.sub.eq(item.user_id),
42
42
  })
43
43
  export class Todo {
44
44
  @uuid() id!: string;
@@ -52,11 +52,11 @@ In this example, authenticated users can only access Todo items where `user_id`
52
52
 
53
53
  ## Type-safe policy expressions
54
54
 
55
- The `check` callback provides typed access to both claims and entity fields.
55
+ The `policy` callback provides typed access to both claims and entity fields.
56
56
  TypeScript infers the entity type from the decorated class, so you get autocompletion and refactor safety with no extra configuration.
57
57
 
58
58
  ```typescript
59
- check: (claims, item) => claims.sub.eq(item.user_id)
59
+ policy: (claims, item) => claims.sub.eq(item.user_id)
60
60
  ```
61
61
 
62
62
  ### Supported claims
@@ -78,7 +78,7 @@ check: (claims, item) => claims.sub.eq(item.user_id)
78
78
  Combine expressions with `.and()` and `.or()`:
79
79
 
80
80
  ```typescript
81
- check: (claims, item) =>
81
+ policy: (claims, item) =>
82
82
  claims.sub.eq(item.user_id).and(item.isActive.eq(true))
83
83
  ```
84
84
 
@@ -86,7 +86,7 @@ Both sides are parenthesized automatically, so grouping is always explicit:
86
86
 
87
87
  ```typescript
88
88
  // (claims.role eq 'admin') or (claims.sub eq @item.owner_id)
89
- check: (claims, item) =>
89
+ policy: (claims, item) =>
90
90
  claims.role.eq('admin').or(claims.sub.eq(item.owner_id))
91
91
  ```
92
92
 
@@ -100,7 +100,7 @@ Only allow the `Title` field during create:
100
100
 
101
101
  ```typescript
102
102
  @role('authenticated', 'create', {
103
- check: (claims, item) => claims.sub.eq(item.createdBy),
103
+ policy: (claims, item) => claims.sub.eq(item.createdBy),
104
104
  include: ['Title'],
105
105
  })
106
106
  ```
@@ -111,7 +111,7 @@ Hide sensitive fields from read operations:
111
111
 
112
112
  ```typescript
113
113
  @role('authenticated', 'read', {
114
- check: (_claims, item) => item.IsAdmin.eq(false),
114
+ policy: (_claims, item) => item.IsAdmin.eq(false),
115
115
  exclude: ['last_login'],
116
116
  })
117
117
  ```
@@ -127,14 +127,14 @@ Apply different rules per action by using multiple `@role` decorators with singl
127
127
  @entity()
128
128
  @role('anonymous', 'read')
129
129
  @role('authenticated', 'create', {
130
- check: (claims, item) => claims.sub.eq(item.createdBy),
130
+ policy: (claims, item) => claims.sub.eq(item.createdBy),
131
131
  include: ['Title'],
132
132
  })
133
133
  @role('authenticated', 'read', {
134
- check: (claims, item) => claims.sub.eq(item.createdBy),
134
+ policy: (claims, item) => claims.sub.eq(item.createdBy),
135
135
  })
136
136
  @role('authenticated', 'update', {
137
- check: (claims, item) => claims.sub.eq(item.createdBy),
137
+ policy: (claims, item) => claims.sub.eq(item.createdBy),
138
138
  exclude: ['adminContent'],
139
139
  })
140
140
  export class SecureDocument {
@@ -155,7 +155,7 @@ import { blob, role } from '@microsoft/rayfin-core';
155
155
 
156
156
  @blob()
157
157
  @role('authenticated', '*', {
158
- check: (claims, item) => claims.sub.eq(item.owner_id),
158
+ policy: (claims, item) => claims.sub.eq(item.owner_id),
159
159
  })
160
160
  export class ProfileImage {
161
161
  owner_id!: string;
@@ -167,6 +167,7 @@ export class ProfileImage {
167
167
  - The `@role` decorator collects permission metadata at class definition time.
168
168
  - When you run `npx rayfin up db apply`, the CLI reads that metadata and generates DAB-compliant permission entries in the configuration.
169
169
  - Policy callbacks are compiled into DAB OData-style policy strings (for example `@claims.sub eq @item.user_id`).
170
+ In the generated DAB configuration the compiled expression appears under a `check` key; `policy` is the name you author with.
170
171
  - Field `include`/`exclude` arrays map directly to DAB field permission configuration.
171
172
  - Multiple `@role` decorators on the same class are aggregated per role.
172
173
  Conflicting declarations produce a warning at generation time.
@@ -14,13 +14,15 @@ Run `npm create @microsoft/rayfin@latest` in a terminal window and select welcom
14
14
 
15
15
  ## Run the app
16
16
 
17
- 1. In a terminal window, run `npx rayfin up` to start the Rayfin backend.
18
- 2. In a second terminal window run `npm run dev` to start the frontend.
17
+ 1. Sign in to Fabric with `npx rayfin login`.
18
+ In an environment without OS credential storage, use `npx rayfin login --encryption-fallback-enabled` only if you accept plaintext token caching for development.
19
+ 2. In the same terminal window, run `npm run dev`.
20
+ The command provisions or reuses the Fabric backend, applies declared state, and starts the frontend locally.
19
21
  3. When the frontend starts, it will output the page to visit.
20
22
  Visit and ensure you can view the Timestamp Tracker.
21
23
  4. Click **Send Timestamp** to POST the current time to `/api/graphql/Timestamp`, then use **Refresh list** to pull back the newest 100 entries.
22
24
  5. All UI plus data-fetching logic lives in a single file: `src/main.ts`.
23
- 6. To point at a different backend, set `RAYFIN_PUBLIC_API_URL` in `rayfin/.env` and re-run `npm run dev` (defaults to `http://localhost:5168`).
25
+ 6. To target a specific Fabric workspace, set `RAYFIN_WORKSPACE_ID` and re-run `npm run dev`.
24
26
 
25
27
  ## Update the data model
26
28
 
@@ -94,7 +96,7 @@ After updating your data models, test your app.
94
96
  npm run dev
95
97
  ```
96
98
 
97
- > NOTE: Any changes to `rayfin.yml` require you to run `npx rayfin up` again.
99
+ > NOTE: Restart `npm run dev` after changing `rayfin.yml` so the backend receives the updated declared state.
98
100
 
99
101
  ## View your local database
100
102
 
@@ -8,15 +8,15 @@ title: Getting Started
8
8
  Rayfin supports two development paths.
9
9
  Choose the one that matches how you want to get started.
10
10
 
11
- ### Local development
11
+ ### Inner-loop development
12
12
 
13
- Run the full Rayfin stack on your machine using Docker.
14
- This path is ideal for building and testing your application before deploying.
13
+ Run frontend and Functions code locally against a managed Rayfin backend.
14
+ Fabric is the default backend provider; the Docker provider is available separately as a preview.
15
+ The default path requires a Microsoft account with Fabric access, an accessible workspace, and the tenant settings needed to create an AppBackend.
15
16
 
16
17
  1. Install prerequisites.
17
18
  1. Scaffold a project with `npm create @microsoft/rayfin@latest` or [add Rayfin to an existing app](../cli/quickstart.md#add-rayfin-to-an-existing-project).
18
- 1. Start backend services with `npx rayfin up`.
19
- 1. Run your frontend with `npm run dev`.
19
+ 1. Start the complete development session with `npm run dev` or `npx rayfin dev`.
20
20
 
21
21
  **Start here:** [Build your first Rayfin app](./create-app-with-cli.md)
22
22
 
@@ -34,7 +34,10 @@ This path requires a Microsoft account with Fabric access and tenant admin setti
34
34
  ## Prerequisites
35
35
 
36
36
  Install these tools before you begin with either path.
37
- Rayfin requires Node.js 20 or later, Docker Desktop (or Docker Engine on Linux), and the GitHub CLI.
37
+ Rayfin requires Node.js 20 or later and the GitHub CLI.
38
+ Docker Desktop or Docker Engine is required only for `rayfin dev --provider docker`.
39
+ Fabric development also requires OS credential storage for the token cache.
40
+ In dev containers, Codespaces, or Linux environments without a keychain, run `npx rayfin login --encryption-fallback-enabled` to explicitly allow the development-only plaintext fallback.
38
41
 
39
42
  ### Windows
40
43
 
@@ -15,6 +15,7 @@ your-project/
15
15
  │ │ ├── schema.ts
16
16
  │ │ └── *.ts
17
17
  │ ├── .env
18
+ │ ├── .project.json
18
19
  │ ├── rayfin.yml
19
20
  │ └── tsconfig.json
20
21
  ├── src/
@@ -184,6 +185,16 @@ Configure an email provider for magic links, password resets, and email verifica
184
185
  `rayfin/.env` is an optional environment file used to supply values to `rayfin.yml` via interpolation.
185
186
  Do not commit secrets, and prefer a `rayfin/.env.example` file for documentation.
186
187
 
188
+ ### rayfin/.project.json
189
+
190
+ `rayfin/.project.json` contains a random project-origin identifier created by `create-rayfin` when anonymous telemetry is enabled.
191
+ The CLI uses it to correlate the original scaffold event with later `rayfin up` deployment events without storing user, machine, workspace, or project names.
192
+ Commit this file so the project keeps the same scaffold lineage across machines, clones, and CI environments.
193
+ You should not need to edit it.
194
+ If you do not want deployments to share the scaffold lineage, you can safely delete `rayfin/.project.json`.
195
+ Deployments continue to work and stop reporting the origin correlation.
196
+ To keep the marker local, add it to `.gitignore` before committing it; if it is already tracked, remove it from source control.
197
+
187
198
  ### rayfin/data/*.ts
188
199
 
189
200
  Files in `rayfin/data/` define your entities.
@@ -280,7 +291,8 @@ export default defineConfig({
280
291
  ### Environment variables
281
292
 
282
293
  Rayfin manages environment variables through `rayfin/.env` using the `RAYFIN_PUBLIC_*` prefix convention.
283
- When you run `npm run dev`, the `predev` hook calls `rayfin env --framework vite` to generate a `.env.local` file with framework-specific variable names.
294
+ When you run `rayfin dev` (or the scaffolded `npm run dev` wrapper), the CLI prepares backend wiring and generates a `.env.local` file with framework-specific variable names before starting the frontend child script.
295
+ The file is written under `services.staticHosting.path` for nested frontends, or at the project root when no path is configured.
284
296
  When the CLI detects a Vite or Next.js project automatically, you can omit `--framework`.
285
297
 
286
298
  The following Vite variables are available in your frontend code after generation:
@@ -290,4 +302,5 @@ The following Vite variables are available in your frontend code after generatio
290
302
  - `VITE_RAYFIN_PUBLISHABLE_KEY` — Publishable key used for Rayfin client authentication.
291
303
  Sourced from `RAYFIN_PUBLIC_PUBLISHABLE_KEY` in `rayfin/.env`.
292
304
 
293
- To override values, edit `rayfin/.env` directly and re-run `rayfin env --framework vite` (or `npm run dev`, which triggers it automatically).
305
+ To override values, edit `rayfin/.env` directly and restart `rayfin dev`.
306
+ You can also run `rayfin env --framework vite` directly when you only need to regenerate the framework file.
@@ -69,14 +69,21 @@ After deployment, the CLI prints the hosting URL and stores it in `rayfin/.deplo
69
69
 
70
70
  #### Skip static deployment during local dev
71
71
 
72
- When iterating locally with `npm run dev` (Vite serves the frontend), pass `--exclude-services staticHosting` to deploy the backend without rebuilding and uploading the static bundle:
72
+ Use `rayfin dev` for the normal inner loop.
73
+ It provisions or reuses the backend and starts Vite locally without publishing static content:
74
+
75
+ ```bash
76
+ rayfin dev
77
+ ```
78
+
79
+ Existing scripts and automation can still run `up` while skipping the static build/package/deploy phase:
73
80
 
74
81
  ```bash
75
82
  rayfin up --exclude-services staticHosting
76
83
  ```
77
84
 
78
85
  This skips only the static build/package/deploy phase — runtime settings are still posted, so previously deployed static content keeps serving from Fabric.
79
- The scaffolded `npm run dev` script in every sample and template uses this flag.
86
+ Rayfin's bundled samples and templates use `rayfin dev` instead.
80
87
 
81
88
  ### Standalone static deployment
82
89
 
@@ -5,15 +5,18 @@
5
5
 
6
6
  ## Overview
7
7
 
8
- The `rayfin dev` command provides a Docker Compose–based local development environment.
9
- It launches containers for enabled services, runs health checks, and auto-applies the database configuration.
8
+ Bare `rayfin dev` uses the Fabric provider by default.
9
+ Pass `--provider docker` to run the managed Rayfin backend and its services through Docker Compose instead.
10
+
11
+ The provider changes only the backend location.
12
+ The frontend and enabled functions always run as local processes during `rayfin dev`.
10
13
 
11
14
  Docker and Docker Compose must be installed and running before using this command.
12
15
 
13
16
  ## Starting the environment
14
17
 
15
18
  ```bash
16
- npx rayfin dev
19
+ npx rayfin dev --provider docker
17
20
  ```
18
21
 
19
22
  This command:
@@ -23,8 +26,29 @@ This command:
23
26
  - Allocates ports for each service.
24
27
  - Starts containers for enabled services (WebService, database, and optional storage).
25
28
  - Runs health checks and waits for all services to be healthy.
29
+ - Applies the project's declared data and storage configuration to the local backend.
30
+ - Starts the frontend with `npm run dev:frontend` when that script exists, falling back to `npm run dev` for existing projects.
31
+ - Resolves that script from `services.staticHosting.path` when the frontend lives in a nested package, otherwise from the project root.
32
+ - Builds and starts the configured local Functions host when `services.functions.enabled` is `true`.
33
+
34
+ The command remains attached to the frontend and Functions processes.
35
+ Press `Ctrl+C` to stop the session and tear down the provider-owned containers.
36
+
37
+ ## Local functions and debugger
38
+
39
+ When functions are enabled, `rayfin dev --provider docker` reserves the nearest free Functions port starting at `7071` and starts Azure Functions Core Tools.
40
+ It writes the selected URL to `RAYFIN_PUBLIC_FUNCTIONS_URL` in `rayfin/.env` and regenerates the framework `.env.local` file.
41
+ When functions are disabled, it removes a stale Functions URL instead.
26
42
 
27
- Wait for the `All services healthy` message before continuing.
43
+ The command also:
44
+
45
+ - Merges local backend settings into the configured functions package's `local.settings.json`.
46
+ - Reserves a Node inspector port starting at `9229`.
47
+ - Adds `Functions: Attach` to the root `.vscode/launch.json` after the Functions host is ready.
48
+ - Patches recognized `src/services/rayfinClient.ts` and `src/services/bootstrap.ts` files to pass `VITE_RAYFIN_FUNCTIONS_URL` as `functionsBaseUrl`.
49
+
50
+ If `.vscode/launch.json` contains JSON with comments, Rayfin leaves it unchanged to avoid losing those comments and asks you to add the attach configuration manually.
51
+ Use `--no-emit-env` to leave a hand-managed `.env.local` file unchanged.
28
52
 
29
53
  ## Stopping and resetting
30
54
 
@@ -32,22 +56,31 @@ Wait for the `All services healthy` message before continuing.
32
56
  |------|----------|
33
57
  | `--stop` | Stop running containers without removing them |
34
58
  | `--down` | Stop and remove containers |
35
- | `--purge` | Stop, remove containers, and delete volumes (full reset) |
59
+ | `--provider docker --purge` | Confirm deletion of provider-owned Docker volumes when the attached session ends |
60
+ | `--down --purge` | Confirm immediate container and volume deletion without starting a session |
61
+ | `--export-env` | Print the retained Docker provider environment in `.env` format |
36
62
 
37
63
  ```bash
38
64
  npx rayfin dev --stop
39
65
  npx rayfin dev --down
40
- npx rayfin dev --purge
66
+ npx rayfin dev --down --purge
67
+ npx rayfin dev --export-env
68
+ npx rayfin dev --provider docker --purge
41
69
  ```
42
70
 
71
+ The retained `--stop`, `--down`, and `--export-env` maintenance actions operate only on Docker state.
72
+ They do not start a workflow session or contact Fabric.
73
+ Purge always requires interactive confirmation or global `--yes` in automation.
74
+ It cannot be combined with `--stop` or `--export-env`.
75
+
43
76
  ## Additional options
44
77
 
45
78
  | Flag | Behavior |
46
79
  |------|----------|
47
- | `--detach` | Run containers in the background |
48
- | `--pull` | Pull latest images before starting |
49
- | `--verbose` | Show detailed Docker output |
50
- | `--debug` | Enable debug logging |
80
+ | `--provider docker` | Select the Docker backend instead of the default Fabric backend |
81
+ | `--skip-db-apply` | Skip automatic data configuration apply |
82
+ | `--no-emit-env` | Leave the existing framework `.env.local` file unchanged |
83
+ | `--verbose` | Show detailed diagnostic output |
51
84
 
52
85
  ## Subcommands
53
86
 
@@ -96,7 +129,7 @@ Changes to `rayfin.yml` require restarting the environment:
96
129
 
97
130
  ```bash
98
131
  npx rayfin dev --down
99
- npx rayfin dev
132
+ npx rayfin dev --provider docker
100
133
  ```
101
134
 
102
135
  ## Troubleshooting
@@ -105,7 +138,8 @@ npx rayfin dev
105
138
  - **`rayfin dev db apply` fails** — make sure services are healthy first (`npx rayfin dev status`).
106
139
  - **Stale services** — stop stale containers with `npx rayfin dev --down`, then restart.
107
140
  - **`unsupported UUID` errors** — stop stale services with `npx rayfin dev --down`.
108
- - **Port conflicts** — use `npx rayfin dev --purge` for a full reset.
141
+ - **Port conflicts** — stop the process using the reported port; Rayfin automatically slides the frontend, Functions, and inspector ports within bounded ranges.
142
+ - **Functions host missing** — install Azure Functions Core Tools by running `npx rayfin dev functions apply`, then retry.
109
143
 
110
144
  ## Enabling this feature
111
145
 
@@ -120,3 +154,6 @@ Or combine with other flags:
120
154
  ```bash
121
155
  export RAYFIN_FEATURE_FLAGS=docker-local-dev,storage
122
156
  ```
157
+
158
+ This feature flag gates only Docker provider selection and Docker maintenance commands.
159
+ Bare `rayfin dev` is available without preview flags and uses Fabric.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/rayfin-guide",
3
- "version": "1.35.0-alpha.1287",
3
+ "version": "1.35.0-alpha.1331",
4
4
  "description": "Cross-cutting Builder guides for the Rayfin platform — discovered by `@microsoft/rayfin-docs` via the `rayfinDocs` package.json field convention.",
5
5
  "type": "module",
6
6
  "files": [