Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
},
"metadata": {
"description": "Claude skills for Dynamicweb 10 — organized by task domain, bundled by role.",
"version": "4.0.1"
"version": "4.0.2"
},
"plugins": [
{
Expand Down
29 changes: 29 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,35 @@
All notable changes to the Dynamicweb Skills plugin are recorded here. The
`version` field in `.claude-plugin/marketplace.json` tracks these entries.

## [4.0.2]

### Fixed
- **License step folded into the canonical first-run flow.** On a fresh DW 10.27.x install the Setup
Guide forces `/admin/license` immediately after the database step, before any admin-user setup.
`dw-demo-base` `scaffold.md` §3 now walks the license step (Suite Trial for demos; ~30-day expiry
recorded in `CUSTOMISATIONS.md`), with the platform-level detail + headless trial path in
`foundational/setup-install.md` §7.
- **Headless admin-password recovery documented.** The license gate can skip the set-admin-password
step, leaving every seeded user inactive with an empty password and no usable admin login.
`foundational/setup-install.md` §7 documents the one-shot `Program.cs` recovery via
`Dynamicweb.Security.UserManagement.UserService` (`ChangePassword` + `user.Active = true` + `Save`).
- **Serializer config path corrected (version-sensitive).** On DW 10.27.4 + engine 0.6.8-beta the
engine reads `Files/System/Serializer/Serializer.config.json`, not the `Files/` root.
`serializer-reference.md` Step 3 (and the config-path mentions in `deserialize-flow.md`) now stage
and cite the `Files/System/Serializer/` location; the engine's actual read location wins, confirmed
by where `SerializeRoot/` is created.
- **Deserialize is a two-POST sequence.** A bare `POST /Admin/Api/SerializerDeserialize` runs the
Deploy pass only; the Seed pass must be requested explicitly with `?mode=Seed`. `deserialize-flow.md`
§4 now documents both passes (deploy then seed) for the swift/2.3 deploy+seed baseline.
- **`excludeAreaColumns` semantics clarified.** The setting governs serialize-OUT (which Area columns
are written to YAML), not deserialize-IN — it does not suppress "source column not present on target
schema" drift for a baseline captured on an older platform. Recovery (strip the column from the
STAGED `area.yml`, never the downloaded original) is documented in `deserialize-flow.md` §3 and the
matching failure pattern in `serializer-reference.md`.

All five folds come from a fresh-DW-10.27.4 autonomous demo build (Serializer engine 0.6.8-beta)
following the skills verbatim — each was a real first-run failure.

## [4.0.1]

### Fixed
Expand Down
44 changes: 44 additions & 0 deletions skills/dw-demo-base/references/foundational/setup-install.md
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,47 @@ debugger, `dotnet watch`, an IDE-managed reload) is respawning it — stop the u
Commerce + Users + Files + Settings + Headless.
- **Do not use the `dotnet new dw10-cms` template** (CMS-only) for a solution that needs Commerce + PIM.
Use `dw10-suite` (the full Suite template).

## 7. First-run license gate + headless admin-password recovery

On a fresh DW **10.27.x** install the Setup Guide forces `/admin/license` immediately after the
database step — **before** any admin-user setup. Complete the license step; a **Suite Trial** is fine
for demos (the trial expiry lands ~30 days out — record it in the demo's `CUSTOMISATIONS.md` so the
next run knows when the demo goes dark). The `dw-setup-install` skill ships a headless
trial-activation path (`scripts/activate-free-trial.ps1`, driving `/admin/license/TrialInstallStep`)
for boxes where the browser flow is not an option.

### 7.1 — The license gate can skip the set-admin-password step

Verified on a fresh 10.27.4 host: when the license step runs first, the Setup Guide can jump straight
past the "set admin password" prompt. The result is a host whose seeded users are all **inactive with
empty passwords** — there is NO usable admin login, and the standard first-run flow dead-ends (every
credential is rejected at `/admin`, with no UI path back to the password prompt).

### 7.2 — Canonical fix: headless password reset via `UserService`

Recover by resetting the admin user in code — a **one-shot** temporary branch in `Program.cs`, removed
after it runs once. Use `Dynamicweb.Security.UserManagement` (`UserManagementServices.Users`, i.e.
`Dynamicweb.Security.UserManagement.UserService`): call `ChangePassword(user, newPassword)`, flip
`user.Active = true`, then `Save(user)`. This API is not on the docs site — it was resolved from the
platform's bin XML docs.

```csharp
// TEMPORARY one-shot — place after the host is built, run once, then DELETE this block.
using Dynamicweb.Security.UserManagement;

var users = UserManagementServices.Users;
// Resolve the seeded admin (by username/id/email — see dw-users-permissions "Reading Users").
var admin = users.GetUserByUserName("Administrator");
if (admin is not null)
{
users.ChangePassword(admin, "<new-strong-password>");
admin.Active = true;
users.Save(admin);
}
```

Restart the host, log in at `/admin` with the new password, then remove the block and restart again so
the reset cannot re-run. Never leave the reset branch in a committed `Program.cs` — it is a
plaintext-password write path. The `ChangePassword` / `Save` surface is the same one documented in
[`../../../dw-users-permissions/SKILL.md`](../../../dw-users-permissions/SKILL.md) ("Writing Users").
3 changes: 2 additions & 1 deletion skills/dw-demo-base/references/scaffold.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ The Setup Guide on first run will:

1. Auto-create the demo database under `MSSQL$SQLEXPRESS` if the connecting SQL user has `dbcreator`. The DB name defaults to the solution folder name unless overridden.
2. Initialise the `Files/` folder under `Dynamicweb.Host.Suite/wwwroot/` with the empty default structure.
3. Print a one-time admin user prompt (capture the credentials — they're needed for the admin UI walkthrough in `references/mcp-setup.md` Step 3).
3. **Force the license step.** On DW 10.27.x the Setup Guide redirects to `/admin/license` immediately after the database step, BEFORE any admin-user setup. Complete it — a **Suite Trial** is fine for demos. The trial expiry lands ~30 days out; record it in the demo's `CUSTOMISATIONS.md` so the next run on this box knows when the demo goes dark. Platform-level detail + the headless trial-activation path: [`foundational/setup-install.md`](foundational/setup-install.md) §7.
4. Print a one-time admin user prompt (capture the credentials — they're needed for the admin UI walkthrough in `references/mcp-setup.md` Step 3). **Gotcha:** the license gate can skip this step entirely, leaving every seeded user inactive with an empty password — no usable admin login, and the standard flow dead-ends. If `/admin` rejects every credential after setup, apply the headless admin-password recovery in [`foundational/setup-install.md`](foundational/setup-install.md) §7 before going further.

Once the Setup Guide completes, the `Properties/launchSettings.json` file has its final `applicationUrl` and the `GlobalSettings.Database.config` has the actual DB name. **These two files are the source of truth for port and DB name from now on** (the discover-from-project-files rule).

Expand Down
12 changes: 9 additions & 3 deletions skills/dw-demo-base/references/serializer-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,19 @@ Copy-Item $dll.FullName "Dynamicweb.Host.Suite\bin\Debug\net10.0\" -Force

The DLL is built net8.0 (Serializer ships single-target net8.0 per its csproj). .NET 10's runtime back-loads net8.0 assemblies fine. Restart the host after the copy so the new DLL is picked up. Note: the README and `docs/getting-started.md` still say "copy to `/path/to/your-dw-host/bin/`" — that's the published-deployment shape and does NOT work for local `dotnet run` hosts; always use the TFM subfolder.

### Step 3 — Stage `Files/Serializer.config.json`
### Step 3 — Stage `Files/System/Serializer/Serializer.config.json`

The Serializer requires a config at `<host>/wwwroot/Files/Serializer.config.json`. Without one, `/Admin/Api/SerializerDeserialize` returns `Serializer.config.json not found (also checked ContentSync.config.json)`. The Serializer repo ships a canonical Swift 2.2 baseline config in the project's `Configuration\` folder — copy that as the starting point:
The Serializer requires a config at `<host>/wwwroot/Files/System/Serializer/Serializer.config.json` (version-sensitive — see the path note below). Without one, `/Admin/Api/SerializerDeserialize` returns `Serializer.config.json not found (also checked ContentSync.config.json)`. The Serializer repo ships a canonical Swift 2.2 baseline config in the project's `Configuration\` folder — copy that as the starting point:

```powershell
$cfgDir = "Dynamicweb.Host.Suite\wwwroot\Files\System\Serializer"
New-Item -ItemType Directory -Path $cfgDir -Force | Out-Null
Copy-Item "$($serializerProj.FullName)\Configuration\swift2.2-combined.json" `
"Dynamicweb.Host.Suite\wwwroot\Files\Serializer.config.json" -Force
"$cfgDir\Serializer.config.json" -Force
```

**Path note (version-sensitive).** On DW **10.27.4** + Serializer engine **0.6.8-beta** the engine reads the config from `Files/System/Serializer/Serializer.config.json`. Older installs staged it at the `Files/` root (`Files/Serializer.config.json`); the engine's actual read location is what wins, so stage it where the running engine looks. Confirm the location on a given host by where the engine creates `SerializeRoot/` — it lands under `Files/System/Serializer/`, alongside the config (the deserialize flow reads `Files/System/Serializer/SerializeRoot/<deploy|seed>/`).

The shipped config uses the current schema: a single flat `predicates: [...]` list with a per-entry `"mode": "Deploy"|"Seed"` field — see "Deploy vs Seed" below for the schema break vs the legacy `deploy: { predicates: [...] }` shape.

### Verification
Expand Down Expand Up @@ -153,6 +157,8 @@ WHERE Link LIKE '%Default.aspx?%=3421%';
2. Drop the column on source: align downward instead of upward.
3. Accept the drift: the column is silently dropped from MERGE, the rest of the row writes correctly. Lenient mode only.

**Area-column drift specifically (older baseline → newer host).** When the offending column is on `[Area]` (e.g. an `area.yml` captured on an older platform), the predicate's `excludeAreaColumns` setting does NOT help — it governs serialize-OUT (which Area columns get *written*), not deserialize-IN. Strip the offending column from the **staged** `Files/System/Serializer/SerializeRoot/deploy/_content/<Area>/area.yml` (never the downloaded original under `baselines\`) and re-POST. See the deserialize flow's §3 note: [`../../dw-demo-swift/references/deserialize-flow.md`](../../dw-demo-swift/references/deserialize-flow.md).

### "template 'T' not found at Files/Templates/T"

**Symptom:** `WARNING: template 'eCom_Catalog' not found at Files/Templates/eCom_Catalog.cshtml`.
Expand Down
Loading
Loading