fimo 2.6.0-staging.1 → 2.6.0-staging.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/skills/fimo-cli/SKILL.md +1 -1
- package/assets/skills/fimo-cli/references/analytics.md +14 -0
- package/assets/skills/fimo-cli/references/content.md +2 -2
- package/assets/skills/fimo-cli/references/hosting.md +11 -0
- package/assets/skills/fimo-code/references/frameworks/next.md +12 -9
- package/assets/skills/fimo-code/references/ui.md +6 -1
- package/assets/skills/fimo-migration/SKILL.md +9 -6
- package/assets/skills/fimo-migration/references/frameworks/nextjs.md +24 -27
- package/assets/skills/fimo-migration/references/media.md +98 -62
- package/assets/skills/fimo-migration/references/qa.md +111 -11
- package/assets/skills/fimo-migration/references/workers/content-execution.md +2 -1
- package/assets/skills/fimo-migration/references/workers/validator.md +22 -6
- package/assets/skills/fimo-migration/references/workers.md +5 -3
- package/assets/skills/fimo-migration/scripts/check-rendered-guardrails.mjs +500 -0
- package/dist/cli/bundle.json +1 -1
- package/dist/cli/index.js +19 -19
- package/dist/runtime/primitives/lib/primitives.d.ts +20 -1
- package/dist/runtime/primitives/lib/primitives.js +24 -1
- package/package.json +10 -9
- package/templates/astro/package.json +2 -2
- package/templates/nextjs/package.json +3 -3
- package/templates/react-router/package.json +4 -4
- package/templates/sveltekit/package.json +2 -2
- package/templates/vite/package.json +4 -4
|
@@ -44,7 +44,7 @@ A Fimo project is identified by `.fimo/project.json`, written by `fimo init`. Th
|
|
|
44
44
|
|
|
45
45
|
## Critical: commands target the Branch matching the current git branch
|
|
46
46
|
|
|
47
|
-
A project can have multiple **Branches** — each is a git branch _plus_ its own DB, sandbox, preview, and assets. Project-scoped commands (`deploy`, `status`, `entries`, `diff`, …) operate on the Branch matching the **current git branch**, and print a one-line banner saying which one. New projects start on `main`. Override for a single command with the canonical `--branch <name>` flag; the removed `--env <name>` spelling is rejected. Never edit the link file to switch. The full git-shaped workflow (`branch` / `checkout` / `switch` / `pull` / `diff` / `merge` / `status` / `publish`) lives in `references/branches.md`.
|
|
47
|
+
A project can have multiple **Branches** — each is a git branch _plus_ its own DB, sandbox, preview, and assets. Project-scoped commands (`deploy`, `status`, `entries`, `diff`, …) operate on the Branch matching the **current git branch**, and print a one-line banner saying which one. Analytics reads are the exception: they default to canonical `prod`, independent of the checkout; see `references/analytics.md`. Annotation writes keep the current or explicit Branch. New projects start on `main`. Override for a single command with the canonical `--branch <name>` flag; the removed `--env <name>` spelling is rejected. Never edit the link file to switch. The full git-shaped workflow (`branch` / `checkout` / `switch` / `pull` / `diff` / `merge` / `status` / `publish`) lives in `references/branches.md`.
|
|
48
48
|
|
|
49
49
|
## Quick Start
|
|
50
50
|
|
|
@@ -4,6 +4,19 @@ Pageview aggregates for the **published** site are stored in Fimo's analytics pi
|
|
|
4
4
|
|
|
5
5
|
Analytics has a **retained preview for every org** — free included. The free default is a 7-day retention window, so short ranges (`today`, `yesterday`, `this_week`, `last_week`, `last_7_days`) work for everyone. **Extended date ranges and longer retention are paid** — `last_30_days`, `last_90_days`, `this_month`, `last_month`, `last_quarter`, `last_year`, and `custom` require the `canUseExtendedDateRanges` privilege, which only paid orgs have. Asking for an extended range as a free user returns a 403 with an upgrade hint.
|
|
6
6
|
|
|
7
|
+
## Select published traffic
|
|
8
|
+
|
|
9
|
+
For traffic, growth, or site-performance questions, read **`prod`**, regardless of the current Git branch, `FIMO_ENV`, or the source branch published to Production. Analytics reads (`pageviews`, `top`, `annotations list`) default to this canonical published target. On older CLI versions, select it explicitly:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
fimo --branch prod analytics pageviews --days 7 --json
|
|
13
|
+
fimo --branch prod analytics top countries --json
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Structured read results include `branch` (`data.branch` in the CLI JSON envelope). Check it before interpreting metrics. An intentional `--branch <name>` overrides the default; zero traffic on `main` or a preview branch does **not** mean the published site has no traffic. Preview visits are not collected. If publication or access is unavailable, report that limitation; do not fall back to another branch or present the failure as zero traffic.
|
|
17
|
+
|
|
18
|
+
SDK and hosted MCP reads also default omitted `branch` to `prod` and return the selected `branch`. Annotation **writes** keep the current/explicit Branch and its existing permissions; the read default does not grant permission to write to `prod`.
|
|
19
|
+
|
|
7
20
|
## Bot traffic is excluded
|
|
8
21
|
|
|
9
22
|
Every number below is **humans only**. Bot hits — AI crawlers and headless browsers — are tagged
|
|
@@ -37,6 +50,7 @@ The headline command returns everything in one payload — KPIs, the visitors se
|
|
|
37
50
|
|
|
38
51
|
```json
|
|
39
52
|
{
|
|
53
|
+
"branch": "prod",
|
|
40
54
|
"range": { "preset": "last_30_days", "effectiveFrom": "...", "effectiveTo": "...", "groupBy": "day", ... },
|
|
41
55
|
"deviceFilter": null,
|
|
42
56
|
"visitors": 1240, "pageviews": 3870, "bounceRate": 42.5, "viewsPerVisit": 3.12, "averageVisitDurationSeconds": 95.4,
|
|
@@ -71,7 +71,7 @@ fimo entries create <TypeName> --body '<json>'
|
|
|
71
71
|
fimo entries create <TypeName> --locale es --document-id <documentId> --body '<json>'
|
|
72
72
|
fimo entries list <TypeName> [--limit N] [--cursor CURSOR] [--all-pages] [--search Q] [--where JSON] [--sort F] [--fields FIELDS] [--populate FIELDS]
|
|
73
73
|
fimo entries list <TypeName> --locale es
|
|
74
|
-
fimo entries get <TypeName> <id> [--locale es]
|
|
74
|
+
fimo entries get <TypeName> <id> [--locale es] [--populate FIELDS]
|
|
75
75
|
fimo entries update <TypeName> <id> [--locale es] --body '<json>'
|
|
76
76
|
fimo entries delete <TypeName> <id> [--locale es]
|
|
77
77
|
fimo entries query (--sql '<select>' | --file <path> | --stdin)
|
|
@@ -101,7 +101,7 @@ Use the canonical read query flags: `--search`, `--sort`, `--where`, `--limit`,
|
|
|
101
101
|
Reference filters take the target `id` string (`{"author":"750e..."}`). On a to-many field, `$eq` and `$contains` mean membership, `$in` means any listed target is present, `$ne` and `$nin` mean none are present, and `$null: true` means empty or missing. Reference fields cannot be sorted; use `--sort field` / `--sort -field` on scalar fields.
|
|
102
102
|
`--fields` is a comma-separated projection for list payloads. The API always keeps `id`, `entryId`, `documentId`, and `locale`; pass only the other fields your view needs, such as `slug,title,excerpt,coverImage`.
|
|
103
103
|
|
|
104
|
-
`--populate` is a comma-separated list of
|
|
104
|
+
`--populate` is a comma-separated list of top-level fields to embed, on `entries list`, `entries get`, and `singles get`. It accepts reference fields, media fields, and blocks fields that contain media; naming a blocks field populates every media value inside it. Nested paths such as `sections.image` are not supported, and other field types return 400. Run `fimo schemas get <TypeName> --json` to inspect field names and types. Without it, reference fields return `{ "id": "..." }` and media fields return the stored `{ "source", "id", "url", "alt" }`; with `--populate author,cover`, `author` returns the target entry for the requested locale and `cover` adds the asset's current `name`, `mime`, `width`, and `height`. Populate never selects which target fields come back. A populated target missing in the requested locale resolves to null unless you pass `localeFallbacks=true`, which falls back to the best available locale variant, marked by its `locale` field. Limits: 200 references per to-many write, 500 distinct populated documents per field per request (400 past either).
|
|
105
105
|
|
|
106
106
|
Polymorphic references declare `targets: ["Post", "Product"]` instead of `target` (never both) and their values carry both parts: `{ "contentType": "Post", "id": "..." }`. Populate returns mixed full entries, and generated hooks expose `$type` on each populated value to branch on. `--where` on polymorphic fields is not supported yet and fails with a clear error. Fixed and polymorphic references also work inside blocks with these same write shapes (`id`, `documentId`, or `slug` selectors), but nested fields cannot be populated or filtered.
|
|
107
107
|
|
|
@@ -33,6 +33,17 @@ Declare redirects, headers, rewrites, and URL shape in
|
|
|
33
33
|
|
|
34
34
|
Every field is optional. Only what you declare is emitted.
|
|
35
35
|
|
|
36
|
+
## Preview and security headers
|
|
37
|
+
|
|
38
|
+
A restrictive application-owned CSP or `X-Frame-Options` policy can block Studio
|
|
39
|
+
Preview. Do not assume automatic header rewriting; Next.js `withFimo` does not
|
|
40
|
+
provide it. Inspect the served policy and scope any manual adaptation to Preview,
|
|
41
|
+
preserving production protections and unrelated headers. `frame-ancestors`
|
|
42
|
+
permits the Studio parent, not the framed app's preview origin. Never derive
|
|
43
|
+
ancestor sources from a preview-origin variable. For `script-src`, `connect-src`,
|
|
44
|
+
`frame-src`, and `form-action`, use resolved/observed Fimo resources and endpoints
|
|
45
|
+
actually used by the iframe. Studio-parent WebSockets do not belong in app CSP.
|
|
46
|
+
|
|
36
47
|
## Matching
|
|
37
48
|
|
|
38
49
|
`source` matches the pathname only, never the query string.
|
|
@@ -46,11 +46,8 @@ own tenant URL.
|
|
|
46
46
|
|
|
47
47
|
## Hosted preview config
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
the application does not set Next's `devIndicators`, the wrapper hides it in
|
|
52
|
-
hosted Preview while local `next dev` keeps Next's default. Any explicit
|
|
53
|
-
`devIndicators` setting is preserved:
|
|
49
|
+
Keep the generated `FimoProvider` and `withFimo` integration to render Fimo
|
|
50
|
+
Preview in Fimo Studio and enable Edit Mode. Wrap the existing Next config once:
|
|
54
51
|
|
|
55
52
|
```ts
|
|
56
53
|
import type { NextConfig } from 'next';
|
|
@@ -60,10 +57,16 @@ const nextConfig: NextConfig = {};
|
|
|
60
57
|
export default withFimo(nextConfig);
|
|
61
58
|
```
|
|
62
59
|
|
|
63
|
-
Preserve
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
Preserve existing config fields and config-function logic. `withFimo` currently
|
|
61
|
+
does not rewrite response headers or adapt application-owned CSP. A restrictive
|
|
62
|
+
policy may need a manual Preview adaptation; inspect actual framing and blocked
|
|
63
|
+
requests, preserve production protections, and verify the result in a browser.
|
|
64
|
+
`frame-ancestors` permits the Studio parent, not the app's preview origin or a
|
|
65
|
+
value derived from a preview-origin variable. `script-src`, `connect-src`,
|
|
66
|
+
`frame-src`, and `form-action` concern resources/endpoints used by the iframe;
|
|
67
|
+
use the resolved connection and observed requests. Never add a Studio-parent
|
|
68
|
+
WebSocket to application CSP. Scope exceptions to Preview and keep unrelated
|
|
69
|
+
security headers unchanged.
|
|
67
70
|
|
|
68
71
|
## Client dependency
|
|
69
72
|
|
|
@@ -53,7 +53,7 @@ Use `<StaticImage>` only when the image is deliberately not editor-managed.
|
|
|
53
53
|
`FimoString`, `FimoBoolean`, and the other tracked values are objects, not primitives: a plain string or boolean cannot carry the source field, locale, and edit-target metadata Fimo editing needs. That gives one two-sided rule:
|
|
54
54
|
|
|
55
55
|
- **MUST** pass the wrapper directly to Fimo rendering primitives (`Text`, `Boolean`, …). Unwrapping first removes the edit target.
|
|
56
|
-
- **MUST** normalize the wrapper before any JavaScript comparison, condition, attribute, or third-party API: `String(value)` for strings, `value.value`
|
|
56
|
+
- **MUST** normalize the wrapper before any JavaScript comparison, condition, attribute, or third-party API: `String(value)` for strings, `value.value` for booleans.
|
|
57
57
|
|
|
58
58
|
```ts
|
|
59
59
|
fimoValue === 'build'; // false — an object never strict-equals a primitive
|
|
@@ -63,6 +63,11 @@ if (fimoFlag) { … } // always runs — an object is truthy even whe
|
|
|
63
63
|
if (fimoFlag.value) { … } // correct
|
|
64
64
|
```
|
|
65
65
|
|
|
66
|
+
Nothing catches `if (fimoFlag)` for you: an object is unconditionally truthy in
|
|
67
|
+
JavaScript, and TypeScript reports no error. Read `.value` every time. A boolean
|
|
68
|
+
field without `required: true` generates `flag?: FimoBoolean`, so read
|
|
69
|
+
`flag?.value`.
|
|
70
|
+
|
|
66
71
|
Keep editable visible text in `<Text>`; normalized primitives are for logic and APIs only, never a substitute for rendering through the primitive.
|
|
67
72
|
|
|
68
73
|
Numeric fields stay plain JavaScript numbers, so they do not carry Studio source metadata. SvelteKit's `Number` component is an optional display/formatting helper; it is not source-editable. Other framework surfaces should render numeric fields normally until a shared tracked-number contract exists.
|
|
@@ -174,18 +174,18 @@ report the exact failed command and setup requirement.
|
|
|
174
174
|
reason. Better modeling never redesigns the site: preserve the source's
|
|
175
175
|
content shape and behavior, and record the source-to-Fimo mapping
|
|
176
176
|
(`references/content.md`).
|
|
177
|
-
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
command cannot carry it (`references/media.md`).
|
|
177
|
+
- Before writing media or wiring `<Image>`, load
|
|
178
|
+
`fimo skills get fimo-migration --ref media` for the stored value, explicit
|
|
179
|
+
`populate`, and responsive-image checks (`references/media.md`).
|
|
181
180
|
- Every write is create-or-update, so any step can be rerun without duplicating
|
|
182
181
|
a schema, entry, asset, single, or label.
|
|
183
182
|
- Every decision cites the source file (and line when it matters) that proves
|
|
184
183
|
it. What no worker could prove stays unresolved with an owner action.
|
|
185
184
|
- Keep coordination evidence in the plain-text files
|
|
186
185
|
`.fimo/migration/migration-plan.md` and
|
|
187
|
-
`.fimo/migration/migration-report.md`. Use JSON
|
|
188
|
-
schema/content payloads
|
|
186
|
+
`.fimo/migration/migration-report.md`. Use JSON for actual Fimo
|
|
187
|
+
schema/content import payloads and the rendered guardrail inventory and
|
|
188
|
+
capture response metadata required by `references/qa.md`. Do not
|
|
189
189
|
create a target description, worker plan, decision registry, or JSON receipt
|
|
190
190
|
just to describe the filesystem or agent work.
|
|
191
191
|
- Do not report completion until the QA gate passes or every failed check is
|
|
@@ -378,6 +378,9 @@ writes go through the normal commands against the linked target:
|
|
|
378
378
|
- `references/workers/content-execution.md` - data import and code-wiring
|
|
379
379
|
contracts.
|
|
380
380
|
- `references/workers/validator.md` - independent fan-in validation.
|
|
381
|
+
- `scripts/check-rendered-guardrails.mjs` evaluates the cited guardrail
|
|
382
|
+
inventory against rendered HTML or a local server and fails closed on empty,
|
|
383
|
+
missing, redirected, or vacuous evidence.
|
|
381
384
|
- `scripts/apply-decision.mjs` and `scripts/write-migration-report.mjs` replay
|
|
382
385
|
an older JSON-ledger migration. A new migration writes the plain-text plan
|
|
383
386
|
and report instead; do not invoke them unless the user asks for that replay.
|
|
@@ -99,8 +99,7 @@ Follow the target project's `fimo-code` Next.js reference and render its
|
|
|
99
99
|
`FimoProvider` once at the application root. The provider uses an explicit
|
|
100
100
|
host connection when one exists; otherwise it resolves the linked project and
|
|
101
101
|
active git branch on the server and passes only the public connection to the
|
|
102
|
-
browser.
|
|
103
|
-
connection.
|
|
102
|
+
browser.
|
|
104
103
|
|
|
105
104
|
Do not create or edit `.env` / `.env.local` for a linked project's Fimo
|
|
106
105
|
connection. Run the project's normal `next dev`, `next build`, and `next start`
|
|
@@ -108,31 +107,29 @@ commands, then exercise at least one server read and one client-side data read.
|
|
|
108
107
|
|
|
109
108
|
## Preview embedding and response headers
|
|
110
109
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
headers carry no unconditional framing block, then mark visual proof
|
|
135
|
-
unavailable in the QA report.
|
|
110
|
+
Keep the generated `FimoProvider` and `withFimo` integration. It supports
|
|
111
|
+
rendering Fimo Preview in Fimo Studio and enabling Edit Mode.
|
|
112
|
+
|
|
113
|
+
The application owns response and security headers; `withFimo` currently does
|
|
114
|
+
not rewrite them or adapt CSP automatically. A restrictive policy may still
|
|
115
|
+
need a manual Preview adaptation. Inspect framing behavior and response headers
|
|
116
|
+
first. Scope changes to Preview, preserve production protections and unrelated
|
|
117
|
+
security headers, and record them in the runtime report's Hosting section.
|
|
118
|
+
When the existing policy sends `X-Frame-Options` or an unconditional
|
|
119
|
+
`frame-ancestors` block, condition or relax that framing control only for the
|
|
120
|
+
verified Preview embedding context; retain it for non-Preview and production
|
|
121
|
+
responses.
|
|
122
|
+
|
|
123
|
+
- `frame-ancestors` controls which Fimo Studio parent may embed the app. The
|
|
124
|
+
incident's manual fix used the current Studio sources `https://fimo.ai` and
|
|
125
|
+
`https://*.fimo.ai`. Verify the Studio parent for the target environment;
|
|
126
|
+
these sources are not a universal resource allowlist. Never derive them from
|
|
127
|
+
a preview-origin variable. The sandbox or hosted preview origin identifies
|
|
128
|
+
the app being framed, not its ancestor.
|
|
129
|
+
- `script-src` controls scripts, `connect-src` API and WebSocket connections,
|
|
130
|
+
`frame-src` frames embedded by the app, and `form-action` form submission
|
|
131
|
+
destinations. Base Fimo sources on the resolved connection and observed
|
|
132
|
+
requests made by the preview iframe, only for resources/endpoints it uses.
|
|
136
133
|
|
|
137
134
|
## Locales
|
|
138
135
|
|
|
@@ -18,7 +18,7 @@ Prefer local files from exports. Use remote URLs when no local file exists.
|
|
|
18
18
|
|
|
19
19
|
## Required Metadata
|
|
20
20
|
|
|
21
|
-
Record what is available:
|
|
21
|
+
Record what is available in the inventory and reports:
|
|
22
22
|
|
|
23
23
|
- source URL or source path
|
|
24
24
|
- filename
|
|
@@ -29,47 +29,50 @@ Record what is available:
|
|
|
29
29
|
- sha256 or another stable hash when possible
|
|
30
30
|
- source references and target references
|
|
31
31
|
|
|
32
|
+
These are migration records, not extra fields to copy into entry media values.
|
|
33
|
+
|
|
32
34
|
## Alt Text Belongs To The Media
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
Preserve each source occurrence's alt on its media value, including an explicit
|
|
37
|
+
empty alt. Do not add a separate schema field or use the filename as alt.
|
|
38
|
+
|
|
39
|
+
Neither `fimo assets upload` nor `fimo assets bulk-upload` currently accepts
|
|
40
|
+
alt metadata: keep the source alt on the value and note that upload limitation
|
|
41
|
+
in the migration report. Population preserves the entry's alt; it does not
|
|
42
|
+
synchronize it with asset alt metadata. If source alt is absent and you write
|
|
43
|
+
a meaningful fallback, identify it as generated in the report.
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
- Never use the filename as alt text.
|
|
43
|
-
- When the source has no alt, a meaningful generated alt is an explicit
|
|
44
|
-
fallback only: mark it with the media item's `altSource`
|
|
45
|
-
(`references/manifest.md`) so an editor can see which alt text the source did
|
|
46
|
-
not provide.
|
|
45
|
+
Use the relevant worker report and `.fimo/migration/migration-report.md` for
|
|
46
|
+
provenance and dispositions. New migrations do not create a canonical
|
|
47
|
+
`manifest.json`; see `fimo skills get fimo-migration --ref manifest` for legacy
|
|
48
|
+
manifest handling.
|
|
47
49
|
|
|
48
50
|
## Dedupe
|
|
49
51
|
|
|
50
|
-
Deduplicate by hash when local bytes are available.
|
|
51
|
-
|
|
52
|
-
|
|
52
|
+
Deduplicate by hash when local bytes are available. Otherwise use canonicalized
|
|
53
|
+
URL plus filename. Keep every source occurrence and its alt even when several
|
|
54
|
+
occurrences reuse one uploaded asset.
|
|
53
55
|
|
|
54
56
|
## Upload And Replacement
|
|
55
57
|
|
|
56
58
|
Referenced media must be uploaded into the Fimo media library. Use
|
|
57
|
-
`fimo assets bulk-upload --file <manifest.json>` for a batch
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
reports
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
spaces,
|
|
59
|
+
`fimo assets bulk-upload --file <manifest.json>` for a batch or
|
|
60
|
+
`fimo assets upload "<file-path>"` for a single file. The bulk-upload input is a
|
|
61
|
+
JSON array with a unique `sourceId` and a `path` per item. Paths resolve from the
|
|
62
|
+
project working directory, not the manifest's directory. Never encode paths or
|
|
63
|
+
names in whitespace-delimited shell input. Load
|
|
64
|
+
`fimo skills get fimo-cli --ref assets` for upload options and result details.
|
|
65
|
+
This upload payload is separate from the migration's Markdown reports.
|
|
66
|
+
|
|
67
|
+
Copying a file under `public/` is not a completed import: editors cannot manage
|
|
68
|
+
it in Fimo and it has no Fimo asset ID/URL. Either upload it and record the Fimo
|
|
69
|
+
target in the worker and migration reports, or mark it `unresolved` with an
|
|
70
|
+
owner action. "Bundled locally, upload later" is not a terminal disposition.
|
|
71
|
+
|
|
72
|
+
If a supplied Fimo migration pack includes a media map, copy its recorded
|
|
73
|
+
`localPath` exactly. Do not reconstruct filenames from source URLs or undo
|
|
74
|
+
normalization of underscores, spaces, or encoded characters. Verify the recorded
|
|
75
|
+
path exists before upload.
|
|
73
76
|
|
|
74
77
|
Replace source references in this order:
|
|
75
78
|
|
|
@@ -78,34 +81,60 @@ Replace source references in this order:
|
|
|
78
81
|
3. page components
|
|
79
82
|
4. form definitions or confirmation content
|
|
80
83
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
the asset owns the uploaded bytes and their metadata
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
84
|
+
Write each imported media field as `{ source, url, alt }`. For an uploaded
|
|
85
|
+
asset, use `{ source: 'local', url, alt }` with the URL returned by Fimo. Do not
|
|
86
|
+
copy the asset's ID, name, MIME type, width, height, or other upload metadata
|
|
87
|
+
into the stored value. The write path resolves and persists the media-library
|
|
88
|
+
ID; the asset owns the uploaded bytes and their metadata. Inspect an asset
|
|
89
|
+
later with `fimo assets open <id> --download`.
|
|
90
|
+
|
|
91
|
+
### Populate and render
|
|
92
|
+
|
|
93
|
+
Use Fimo media primitives for schema media rather than hardcoded URLs. Load
|
|
94
|
+
`fimo skills get fimo-code --ref ui` and the detected framework reference for
|
|
95
|
+
component imports and usage.
|
|
96
|
+
|
|
97
|
+
Explicitly populate the media field before wiring it to `<Image>`. Without
|
|
98
|
+
`populate`, a read returns the stored reference `{ source, id, url, alt }`,
|
|
99
|
+
including its fallback URL, but does not look up current asset metadata. With
|
|
100
|
+
the field named in `populate`, it returns current asset facts from the library:
|
|
101
|
+
URL, name, MIME type, and intrinsic width and height when available.
|
|
102
|
+
|
|
103
|
+
For media inside blocks, name the top-level blocks field, for example
|
|
104
|
+
`--populate sections` or
|
|
105
|
+
`populate: ['sections'] as const`, not a nested image path. This populates all
|
|
106
|
+
media inside that field.
|
|
107
|
+
|
|
108
|
+
CLI examples:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
fimo entries list BlogPost --limit 1 --populate cover --json
|
|
112
|
+
fimo entries get BlogPost <entry-id> --populate cover --json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Generated-client example:
|
|
116
|
+
|
|
117
|
+
```tsx
|
|
118
|
+
const article = await BlogPost.getBySlug('hello', { populate: ['cover'] as const });
|
|
119
|
+
return article ? <Image value={article.cover} sizes="100vw" /> : null;
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Before completing the migration, verify that the populated raster has its
|
|
123
|
+
intrinsic `width` and `height`. Render the page at desktop and mobile widths,
|
|
124
|
+
then check the optimized responsive `srcset`. With optimization enabled on an
|
|
125
|
+
eligible Fimo URL, `sizes` set, and no custom `srcSet`, its generated width
|
|
126
|
+
candidates stop at the intrinsic width. Choose displayed size, crop, `sizes`,
|
|
127
|
+
and fit from the source layout; intrinsic dimensions are source facts, not
|
|
128
|
+
layout choices. Fix a missing `populate` request instead of copying metadata
|
|
129
|
+
into the entry or hardcoding intrinsic dimensions. If a populated read still
|
|
130
|
+
lacks dimensions, report the gap rather than inventing them.
|
|
99
131
|
|
|
100
132
|
## Failure Handling
|
|
101
133
|
|
|
102
|
-
If
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
- list every page/entry that references it
|
|
107
|
-
- include a suggested action such as re-exporting the asset folder or providing
|
|
108
|
-
credentials
|
|
134
|
+
If an asset cannot be downloaded or uploaded, keep its source reference,
|
|
135
|
+
record `unresolved` or `unsupported` in the report, and list affected
|
|
136
|
+
pages/entries, the failure reason, and an owner action, such as re-exporting the
|
|
137
|
+
asset folder or providing credentials.
|
|
109
138
|
|
|
110
139
|
## Media obligations
|
|
111
140
|
|
|
@@ -115,8 +144,15 @@ terminal, the coordinator combines and deduplicates those findings into the
|
|
|
115
144
|
complete media-obligation list. This consolidated list is the media worker's
|
|
116
145
|
only input; do not make the content planner rescan the whole application.
|
|
117
146
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
147
|
+
Keep one migration mapping per source occurrence: source file or page, field
|
|
148
|
+
or rich-text node path, consuming route/entry, and target field or node plus
|
|
149
|
+
the uploaded asset ID/URL. Use the source location and field or node path for
|
|
150
|
+
stable identity. A shared URL or label is not a unique occurrence;
|
|
151
|
+
retain every mapping even when occurrences reuse one uploaded asset.
|
|
152
|
+
|
|
153
|
+
The media worker cannot report complete until every obligation has an uploaded
|
|
154
|
+
or duplicate Fimo mapping, or an explicit unresolved/unsupported disposition.
|
|
155
|
+
Reconcile the mappings against every discovery lane's findings, including
|
|
156
|
+
schema media fields and nested richtext/Tiptap image nodes. Run the broader
|
|
157
|
+
migration gate from `fimo skills get fimo-migration --ref qa` before claiming
|
|
158
|
+
the migration is complete.
|
|
@@ -104,8 +104,7 @@ items.
|
|
|
104
104
|
|
|
105
105
|
For linked Next.js targets, the root `FimoProvider` resolves an explicit host
|
|
106
106
|
connection first, otherwise `.fimo/project.json` plus the active git branch,
|
|
107
|
-
and passes only the public connection to the browser. `
|
|
108
|
-
hosted preview origins, not this connection. Run the normal `next dev`,
|
|
107
|
+
and passes only the public connection to the browser. Run the normal `next dev`,
|
|
109
108
|
`next build`, and `next start` commands without creating a Fimo env file.
|
|
110
109
|
|
|
111
110
|
## Hosting
|
|
@@ -113,18 +112,23 @@ hosted preview origins, not this connection. Run the normal `next dev`,
|
|
|
113
112
|
Owned by the runtime lane; verified here read-only.
|
|
114
113
|
|
|
115
114
|
- The target starts locally: the dev server responds without startup errors.
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
`
|
|
115
|
+
- Fimo Preview renders the target in Fimo Studio and Edit Mode works. If either
|
|
116
|
+
is blocked, verify the actual framing behavior and response headers. The
|
|
117
|
+
application owns its security policy; any Preview exception must preserve
|
|
118
|
+
production protections and unrelated security headers.
|
|
119
|
+
- Check CSP sources by purpose: `frame-ancestors` permits the Studio parent;
|
|
120
|
+
the app's preview origin is the framed site. `script-src`, `connect-src`,
|
|
121
|
+
`frame-src`, and `form-action` use resolved/observed Fimo resources and
|
|
122
|
+
endpoints actually used by the iframe. Do not copy ancestor sources into
|
|
123
|
+
resource directives or derive them from a preview-origin variable.
|
|
124
|
+
- `withFimo` does not rewrite response headers. Verify any required manual
|
|
125
|
+
Preview adaptation of an application-owned restrictive policy.
|
|
123
126
|
- The runtime report covers local startup, preview embedding, build, the
|
|
124
127
|
resolved Fimo connection, header translations, and integration env-key
|
|
125
128
|
names, with every claim backed by evidence.
|
|
126
129
|
- With a browser available, record `browserProof` (rendered route plus console
|
|
127
|
-
state) for startup and
|
|
130
|
+
state) for startup, Studio embedding, and Edit Mode. Build or HTTP checks alone
|
|
131
|
+
do not prove these work. Without a browser, use deterministic HTTP
|
|
128
132
|
status/header/process/log checks and mark visual proof explicitly
|
|
129
133
|
unavailable in the report.
|
|
130
134
|
- Deployment smoke is explicit owner opt-in; never run deploy or publish as a
|
|
@@ -157,12 +161,102 @@ Owned by the runtime lane; verified here read-only.
|
|
|
157
161
|
fetched again after hydration. A new client waterfall, repeated full-list
|
|
158
162
|
read, avoidable sequential request chain, or stale edit fails the responsible
|
|
159
163
|
migration lane.
|
|
160
|
-
- Navigation and footer links point to migrated routes or documented external
|
|
164
|
+
- Navigation and footer links point to migrated routes or documented external
|
|
165
|
+
URLs. The `links-resolve` rule below checks internal routes; the validator
|
|
166
|
+
reviews external destinations separately.
|
|
161
167
|
- Missing integration secrets do not block these checks: build, dev, and route
|
|
162
168
|
render run with the integration inert, and the missing key is a recorded
|
|
163
169
|
follow-up.
|
|
164
170
|
- Unsupported app behavior is not hidden behind broken UI.
|
|
165
171
|
|
|
172
|
+
## Rendered guardrails (required)
|
|
173
|
+
|
|
174
|
+
Brand, legal, compliance, and navigation rules are proven on the final rendered
|
|
175
|
+
application, never by grepping the target source. Once copy moves into Fimo the
|
|
176
|
+
strings leave the repository: a source grep for a forbidden phrase passes
|
|
177
|
+
because nothing is there, and a grep for the brand name fails for the same
|
|
178
|
+
reason. Worker reports, manifests, and coverage tables are diagnostics; this
|
|
179
|
+
check is the acceptance evidence.
|
|
180
|
+
|
|
181
|
+
1. Before the validation wave, the coordinator writes the guardrail inventory to
|
|
182
|
+
`.fimo/migration/guardrails.json` for the deterministic checker. List every
|
|
183
|
+
route the migration must prove and every rule the source, owner, or accepted
|
|
184
|
+
scope imposes. Every rule includes `source`: the source page, file, or owner
|
|
185
|
+
decision that requires it. A rule without a citation is an invention, not a
|
|
186
|
+
recovered project guardrail.
|
|
187
|
+
- `required-text`: copy that must render, such as the brand name or a
|
|
188
|
+
legally required notice.
|
|
189
|
+
- `forbidden-text`: copy that must never render, such as an old brand name,
|
|
190
|
+
placeholder text, or a claim the owner withdrew.
|
|
191
|
+
- `required-link`: a link every page must carry, such as the privacy policy
|
|
192
|
+
or imprint.
|
|
193
|
+
- `links-resolve`: every internal link rendered on the inventoried routes
|
|
194
|
+
points at an inventoried route or an explicitly allowed path prefix.
|
|
195
|
+
|
|
196
|
+
Internal links are resolved against the final document URL and any
|
|
197
|
+
`<base href>`; query and fragment do not change route identity. An `allow`
|
|
198
|
+
prefix exempts a destination family deliberately outside the accepted scope.
|
|
199
|
+
|
|
200
|
+
Scope a rule with `routes` only when it is not global. When the source has
|
|
201
|
+
no rule of a kind (for example no legal page), say so in the migration
|
|
202
|
+
report rather than leaving the inventory thin without explanation.
|
|
203
|
+
|
|
204
|
+
```json
|
|
205
|
+
{
|
|
206
|
+
"routes": ["/", "/about", "/legal/privacy"],
|
|
207
|
+
"rules": [
|
|
208
|
+
{ "id": "brand-name", "kind": "required-text", "text": "<target brand>", "source": "<source page or file>" },
|
|
209
|
+
{
|
|
210
|
+
"id": "no-old-brand",
|
|
211
|
+
"kind": "forbidden-text",
|
|
212
|
+
"text": ["<previous brand>", "Lorem ipsum"],
|
|
213
|
+
"source": "<owner decision>"
|
|
214
|
+
},
|
|
215
|
+
{ "id": "footer-privacy", "kind": "required-link", "href": "/legal/privacy", "source": "<source navigation>" },
|
|
216
|
+
{ "id": "nav-resolves", "kind": "links-resolve", "allow": ["/blog"], "source": "<source navigation>" }
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
2. The validator observes the rendered application, not files in the
|
|
222
|
+
repository. For a server-rendered target, run the check with `--base-url`
|
|
223
|
+
while the built app serves locally. For a client-rendered target, save each
|
|
224
|
+
hydrated document from the browser pass as `<captures>/index.html` and
|
|
225
|
+
`<captures>/<route>.html` and pass `--captures`. Save a JSON sidecar next to
|
|
226
|
+
each HTML file, such as `index.html.json` or `legal/privacy.html.json`:
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{ "status": 200, "url": "http://localhost:3000/legal/privacy", "error": null }
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Record the actual final navigation response status and document URL,
|
|
233
|
+
including its trailing slash. Record navigation or capture failures in
|
|
234
|
+
`error`; never infer a successful status from HTML or fill in missing
|
|
235
|
+
evidence. Missing, malformed, non-200, or error metadata fails the route.
|
|
236
|
+
Captures are supplied evidence: the checker cannot authenticate them or
|
|
237
|
+
recognize every error page served with status 200. The browser smoke below
|
|
238
|
+
must still prove representative content and working controls.
|
|
239
|
+
|
|
240
|
+
Count visitor-visible body text and readable attributes (`alt`, `title`,
|
|
241
|
+
`aria-label`, `placeholder`, and `meta` content); script, style, and comment
|
|
242
|
+
strings do not count.
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
node node_modules/fimo/assets/skills/fimo-migration/scripts/check-rendered-guardrails.mjs <target> \
|
|
246
|
+
--base-url http://localhost:3000 --output .fimo/migration/guardrails-report.md
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
3. The check fails closed and caps the gate at `draft-only` when the inventory
|
|
250
|
+
or rendered evidence is empty, a route is missing or non-200, a final URL
|
|
251
|
+
does not match the inventoried route, or a rule observes nothing. Nothing
|
|
252
|
+
observed is failed, never passed.
|
|
253
|
+
|
|
254
|
+
4. Copy the emitted `## Guardrails` block unchanged into the validator's
|
|
255
|
+
worker report and the migration report. Acceptance is `Result: passed` with
|
|
256
|
+
every inventoried route rendered and every rule observed on at least one
|
|
257
|
+
route. Each failure names the route and the phrase or link involved, so the
|
|
258
|
+
repair owner needs no rerun to locate it.
|
|
259
|
+
|
|
166
260
|
## Browser smoke (required)
|
|
167
261
|
|
|
168
262
|
Build success and HTTP 200 responses are not sufficient evidence: a page can
|
|
@@ -262,6 +356,8 @@ complete | complete-with-unresolved | draft-only
|
|
|
262
356
|
|
|
263
357
|
## Content Delivery
|
|
264
358
|
|
|
359
|
+
## Guardrails
|
|
360
|
+
|
|
265
361
|
## Timing
|
|
266
362
|
|
|
267
363
|
## Checks
|
|
@@ -279,6 +375,10 @@ locales) with `gate`,
|
|
|
279
375
|
coverage must not average away a missing entry or an unuploaded asset. Timing is
|
|
280
376
|
a separate section copied from the worker reports, so it never dilutes coverage.
|
|
281
377
|
|
|
378
|
+
`Guardrails` is the unmodified block emitted by
|
|
379
|
+
`scripts/check-rendered-guardrails.mjs`. A report without it, or with
|
|
380
|
+
`Result: failed`, cannot be `complete` or `complete-with-unresolved`.
|
|
381
|
+
|
|
282
382
|
Cache freshness is a report check whenever migration changes the content
|
|
283
383
|
transport or rendering mode. Do not fail a migration for omitted provider cache
|
|
284
384
|
mechanics alone, but do fail stale Fimo edits caused by the target's migrated
|