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
33 changes: 33 additions & 0 deletions .yarn/changelogs/common.157e03c9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<!-- version-type: patch -->
# common

## ✨ Features

- Added optional `regenerateIds` flag to the `POST /stacks/import` request body (`ImportStackEndpoint`). When set to `true`, the server assigns fresh UUIDs to every service, repository, and prerequisite during import and remaps cross-entity references (`prerequisiteIds`, `prerequisiteServiceIds`, and the `config.services` map). Use this to duplicate a stack on the same machine without ID collisions with the source stack.

## 🐛 Bug Fixes

### `ApplyServiceFilesEndpoint` result shape carries unresolved template placeholders

`ApplyServiceFilesEndpoint.result.applied` is now `AppliedServiceFile[]` (each entry `{ relativePath: string; unresolved: string[] }`) instead of the previous opaque `string[]`. The new `unresolved` array lists every distinct `{{NAME}}` placeholder that remained in the written file because no matching key was present in the resolved environment — the file is still written verbatim, but consumers can now warn the user about the name mismatch instead of leaving placeholders behind without feedback.

**Impact:** existing API consumers that read `result.applied` as a string list of relative paths must switch to `result.applied.map((a) => a.relativePath)`. The JSON schema in `common/schemas/services-api.json` is regenerated to match the new shape.

## 💥 Breaking Changes

### Stack Export Format No Longer Includes `stackName` on Child Entities

`ShareableServiceDefinition`, `ShareableGitHubRepository`, and `ShareablePrerequisite` no longer carry a `stackName` field. The value is always equal to the top-level `stack.name` and was pure duplication on the wire — for a stack with N services + M repos + P prereqs the export emitted N+M+P copies of the same string.

**Impact:**

- Stack JSON files exported by older versions cannot be re-imported without first removing the `stackName` field from each service / repository / prerequisite entry. The import action validates the request body against the JSON schema, which now rejects extra properties.
- Tools or scripts that constructed an import payload programmatically and set `stackName` on child entities need to drop that field.

**Migration:** strip the `stackName` field from every entry under `services[]`, `repositories[]`, and `prerequisites[]` in any saved export JSON. The top-level `stack.name` already carries the value.

## ⬆️ Dependencies

- Bumped `@furystack/core` from `^17.0.0` to `^17.1.0` (minor). Pulls in additive type exports; no source changes in `common`.
- Bumped `@furystack/rest` from `^10.0.0` to `^10.0.1` (patch).
- Bumped dev `@types/node` from `^25.6.0` to `^25.9.1` and `vitest` from `^4.1.5` to `^4.1.7` (patch). Dev-tooling only.
38 changes: 38 additions & 0 deletions .yarn/changelogs/frontend.157e03c9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<!-- version-type: patch -->
# frontend

## ✨ Features

### "Import as Duplicate" Toggle on the Import Stack Page

Added an "Import as duplicate (generate new IDs)" checkbox below the main directory input on the Import Stack page. When enabled, the request is sent with `regenerateIds: true` and the server assigns fresh UUIDs to every imported service, repository, and prerequisite, remapping inter-entity references accordingly. Use this when importing a copy of a stack that already exists on this machine — without it, the import is rejected with a 409 conflict listing every colliding entity ID.

The checkbox is off by default to preserve the "cross-machine restore with stable IDs" flow.

## 🐛 Bug Fixes

### Adding an Env Variable in `Requirement` Mode No Longer Persists a Custom Value

Adding an environment variable through `EnvironmentVariablesManager` (stack edit page) or `ServiceEnvOverrides` (service detail page) with `Mode: Requirement (creates prerequisite)` previously wrote a `{ source: 'custom', customValue: '…' }` entry into the stack/service config in addition to creating the prerequisite. The variable then appeared with the `Custom` badge after refresh.

`Requirement` mode now ONLY creates the prerequisite. Use the prerequisite row that appears afterwards to pick `Inherit from system` or set a stack/service-level custom value. `Custom only (local)` mode behavior is unchanged.

## ♻️ Refactoring

- `EnvironmentVariablesManager` and `ServiceEnvOverrides` add forms: `Source` select and value input are now hidden when `Mode: Requirement` is selected — the prereq row drives value resolution after creation, so collecting the source/value alongside prereq creation was redundant and confusing.

## ⬆️ Dependencies

### `@furystack/cache` 7 → 8 (major)

Bumped to pick up the tag-based invalidation API (`getTags`, `obsoleteByTag`, `removeByTag`) that replaces the removed predicate-based `obsoleteRange` / `removeRange`. The frontend does not call the removed APIs directly, so no migration was required.

### `@furystack/entity-sync` 2 → 3 + `@furystack/entity-sync-client` 3 → 4 (major)

Bumped together. `SyncVersion.seq` / `ClientSyncMessage.lastSeq` / `SyncCacheEntry.lastSeq` are now opaque adapter-assigned strings instead of numeric counters — clients must not perform arithmetic or ordered comparison on them. `AppEntitySyncService` does not configure a `localStore`, so there is no persisted cache to invalidate on this upgrade. No code changes were needed in `frontend/src/services/entity-sync.ts`.

### Other bumps

- `@furystack/core` `^17.0.0` → `^17.1.0` (minor).
- `@furystack/inject` `^13.0.0` → `^13.0.1`, `@furystack/logging` `^9.0.0` → `^9.0.1`, `@furystack/rest-client-fetch` `^9.0.0` → `^9.0.1`, `@furystack/shades` `^15.0.0` → `^15.0.1`, `@furystack/shades-common-components` `^17.0.0` → `^17.0.1`, `@furystack/shades-mfe` `^5.0.0` → `^5.0.1`, `@furystack/utils` `^9.0.0` → `^9.0.1` (patch).
- Bumped dev `@types/node` `^25.6.0` → `^25.9.1`, `vite` `^8.0.10` → `^8.0.14`, `vitest` `^4.1.5` → `^4.1.7` (patch).
16 changes: 16 additions & 0 deletions .yarn/changelogs/frontend.b4e99528.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,22 @@
<!-- version-type: patch -->
# frontend

## ✨ Features

### Bulk "Apply Files" for selected services

The bulk action bar on `/stacks/:stackName/services` now exposes an **Apply Files** button alongside Start / Stop / Setup / Restart / Update. Selecting one or more services and clicking it calls `POST /services/:id/apply-files` for each in sequence, surfacing a single success Noty, an aggregated `warning` Noty listing unresolved `{{NAME}}` placeholders grouped by service, and an `error` Noty for any services that failed outright. Failures on one service do not abort the rest — every selection is attempted.

This unblocks the "I edited stack environment variables and want every service file re-applied" flow without visiting every service detail page.

## 🐛 Bug Fixes

### `applyServiceFiles` surfaces unresolved template placeholders

The service-detail Files-tab "Apply" / "Apply All" button now emits a second `warning` Noty when the server reports any unresolved `{{NAME}}` placeholders for the written file(s). The message lists the missing variables (e.g. `.env: POSTGRES_USER, POSTGRES_PASSWORD`) so the user can correct the name mismatch in the stack environment instead of wondering why the file content was not interpolated.

## 🧪 Tests

- Added `bulk-actions.spec.ts` covering the new `bulkApplyFiles` helper (success Noty, warning Noty grouping by service, error Noty on per-service failures, no-warning happy path, and the `formatUnresolvedSummary` helper).
- Extended `service-detail/utils.spec.ts` with two new `applyServiceFiles` cases asserting the warning Noty appears for unresolved placeholders and stays absent when every placeholder is resolved.
- Replaced hard-coded `/tmp/...` paths in the payload-validator specs (`stack-form.spec.ts`, `import-stack.spec.ts`) with `os.tmpdir()`-based equivalents so the frontend `vitest` suite runs unmodified on Windows hosts (where `/tmp` does not exist) in addition to Linux and macOS.
6 changes: 6 additions & 0 deletions .yarn/changelogs/monaco-mfe.157e03c9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<!-- version-type: patch -->
# monaco-mfe

## ⬆️ Dependencies

- Bumped `vite` from `^8.0.10` to `^8.0.14` (patch). No source changes — keeps the Monaco MFE on the same Vite revision as the rest of the workspace.
46 changes: 46 additions & 0 deletions .yarn/changelogs/service.157e03c9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<!-- version-type: patch -->
# service

## ✨ Features

### Duplicate a Stack via Import with Fresh Entity IDs

`POST /stacks/import` now accepts an optional `regenerateIds: true` flag. When set, the import action replaces every incoming service / repository / prerequisite ID with a freshly generated UUID before the conflict check runs, and remaps cross-entity references (`services[].prerequisiteIds`, `services[].prerequisiteServiceIds`, and the `config.services` map keys) to the new IDs.

This unblocks the "export → import as duplicate under a new stack name + directory" flow on the same machine, where previously every entity ID collided with the source stack and the import was rejected with a 409 conflict.

## 🐛 Bug Fixes

- The conflict error returned by `POST /stacks/import` when entity IDs already exist now mentions the `regenerateIds` request flag (and the matching "Import as duplicate" UI toggle), instead of only listing the colliding IDs.

## ♻️ Refactoring

### Stack Export Strips `stackName` From Every Child Entity

`GET /stacks/:id/export` no longer emits `stackName` on each service, repository, or prerequisite in the response body. The value was always identical to the top-level `stack.name` and was pure repetition on the wire (one extra string per child entity). Imports already overwrote the incoming value with `stack.name`, so removing it from the wire shape has no behavioural effect, only a smaller payload.

See the `common` changelog for the breaking impact on previously saved export JSON files.

## 🧪 Tests

- Added `regenerate-import-ids.spec.ts` covering the ID remap helper: top-level entity ID regeneration, `prerequisiteIds` / `prerequisiteServiceIds` remap, `config.services` rekeying, input non-mutation, and orphan-reference pass-through.
- Extended `import-export-actions.spec.ts` with an end-to-end duplicate-import test (same payload imported twice under different stack names with `regenerateIds: true`) and an assertion that the conflict error message references the new flag.
- Updated existing import-action specs to construct payloads without `stackName` on child entities, matching the new contract.

## ⬆️ Dependencies

### `@furystack/entity-sync-service` 2 → 3 (major)

Bumped to pick up the bus-backed `SubscriptionManager`. `SubscriptionManager` now publishes / subscribes through the new `EntityChangeBus` (built on `@furystack/cross-node-bus`), `getModelRegistration()` returns `currentSeq: string` (without `changelogLength`), and `subscribeEntity(..., lastSeq?: string)` matches the new wire format. `stack-craft` is a single-node deployment, so the default in-process bus binding applies — no `CrossNodeBus` adapter is needed and no app wiring changes were required.

### Minor bumps

- `@furystack/core` `^17.0.0` → `^17.1.0`.
- `@furystack/rest-service` `^14.0.0` → `^14.1.0`.
- `@furystack/websocket-api` `^14.0.0` → `^14.1.0`.

### Patch bumps

- `@furystack/inject` `^13.0.0` → `^13.0.1`, `@furystack/logging` `^9.0.0` → `^9.0.1`, `@furystack/repository` `^11.0.0` → `^11.0.1`, `@furystack/security` `^8.0.0` → `^8.0.1`, `@furystack/sequelize-store` `^7.0.0` → `^7.0.1`.
- `pg` `^8.20.0` → `^8.21.0`.
- Dev `@types/node` `^25.6.0` → `^25.9.1`, `vitest` `^4.1.5` → `^4.1.7`.
10 changes: 10 additions & 0 deletions .yarn/changelogs/service.b4e99528.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@

## 🐛 Bug Fixes

### Unresolved `{{NAME}}` template placeholders are no longer a silent no-op on Apply

`POST /services/:id/apply-files` previously returned `applied: string[]` and silently left any unmatched `{{NAME}}` placeholder verbatim in the written file. Users editing stack environment variables and re-applying a file had no way to tell that interpolation had not happened (e.g. when a file template references `{{POSTGRES_USER}}` but the stack defines `TTC_MRK_POSTGRES_USER`).

The response shape is now `applied: AppliedServiceFile[]` where each entry carries `{ relativePath, unresolved: string[] }`. The new `unresolved` array lists every distinct placeholder that remained in the written content, in first-appearance order. Files are still written verbatim — the change is purely additive feedback so the caller can warn the user.

`GitOperationsService.applySharedFiles` (run as part of `cloneOrPullService` during setup / update) now logs a warning that lists per-file unresolved placeholders alongside the existing "Applied N file(s)" info line, surfacing the same mismatch during initial provisioning. The MCP `apply_service_files` / `apply_service_file` tools include the same list in their text result.

### Yarn prerequisite check now resolves on Windows

`checkYarn` previously called `execFile('yarn', ['--version'])`, which fails on Windows because Yarn is installed as a `yarn.cmd` / `yarn.ps1` shim — `execFile` does not consult `PATHEXT` and therefore reports the prerequisite as "not matched". On Windows the call is now routed through `cmd.exe /c yarn --version` so the shim is resolved like it is in any interactive shell. POSIX still uses `execFile` directly.
Expand All @@ -13,5 +21,7 @@

## 🧪 Tests

- Added `apply-service-files` cases that assert the new `{ relativePath, unresolved }` shape on apply, including deduplication of repeated placeholders, propagation of partial resolution, and a standalone `collectUnresolvedPlaceholders` spec covering first-appearance order against the `{{NAME}}` pattern.
- Extended `service-file-manager` spec with a case that asserts unresolved placeholders are propagated from the apply util through the manager.
- Added a Windows-specific `killProcessGroup` spec asserting `taskkill` is invoked **without** `/F` for `SIGTERM` and **with** `/F` for `SIGKILL`.
- Replaced hard-coded `/tmp/...` literals in service specs with `os.tmpdir()`-based paths (`join(tmpdir(), '...')`) so spec runs are portable across Linux, macOS, and Windows. Affected specs: `git-operations-service`, `git-watcher`, `git-head-watcher`, `service-delete-branch-action`, `import-export-actions`, `create-stack-action`, `service-branches-action`, `resolve-service-cwd`, `encrypt-existing-secrets`, `service-pipeline-orchestrator`, `service-env-resolver`, `stale-state-reconciler`, `service-file-manager`, `service-checkout-action`, `check-prerequisite-action`, `evaluate-prerequisites`. The two `/tmp` references that remain in `process-runner.spec.ts` are intentional — they pair with explicit `process.platform = 'linux'` mocks that exercise the POSIX `'/bin/sh'` branch.
42 changes: 42 additions & 0 deletions .yarn/changelogs/stack-craft.157e03c9.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!-- version-type: patch -->
# stack-craft

## ✨ Features

- Added support for importing a stack as a duplicate on the same machine via a new `regenerateIds` flag on `POST /stacks/import` and an "Import as duplicate" checkbox on the Import Stack page. See the `service` and `frontend` changelogs for details.

## ♻️ Refactoring

- Stack export JSON is smaller: the redundant `stackName` field has been removed from every service / repository / prerequisite entry. The value lives once at the top-level `stack.name`. See the `common` changelog for breaking impact on saved export files.

## 🐛 Bug Fixes

- Fixed stack/service env variable add form persisting a phantom `{ source: 'custom' }` entry when `Mode: Requirement` was chosen. See the `frontend` changelog for details.

## ⬆️ Dependencies

### Tooling majors

- `@furystack/eslint-plugin` `^3.0.0` → `^4.0.0`. Removed rule `furystack/no-removed-shade-apis`; the rule is not referenced directly in `eslint.config.js` (only bundled configs are used), so no config change was needed.
- `eslint-plugin-jsdoc` `^62.9.0` → `^63.0.0`. Drops Node 20 support — see 🔧 Chores.
- `lint-staged` `^16.4.0` → `^17.0.5`. Drops Node 20 support and now requires Git ≥ 2.32 (workspace ships with 2.43+, no impact). The optional `yaml` dependency is no longer auto-installed, but `lint-staged` config lives in `package.json`, so this does not affect the project.

### Tooling minors / patches

- `@playwright/test` `^1.59.1` → `^1.60.0`.
- `eslint` `^10.2.1` → `^10.4.0`.
- `typescript-eslint` `^8.59.0` → `^8.59.4`.
- `@vitest/coverage-v8` `^4.1.5` → `^4.1.7`, `vitest` `^4.1.5` → `^4.1.7`, `vite` `^8.0.10` → `^8.0.14`.
- `jsdom` `^29.0.2` → `^29.1.1`.
- `@types/node` `^25.6.0` → `^25.9.1`.
- Yarn release bumped from `yarn-4.14.1.cjs` to `yarn-4.15.0.cjs`.

Per-workspace dependency notes — including the `@furystack/cache` 7 → 8, `@furystack/entity-sync` 2 → 3, `@furystack/entity-sync-client` 3 → 4, and `@furystack/entity-sync-service` 2 → 3 major bumps and their impact assessment — live in the `common`, `frontend`, and `service` changelogs.

## 🔧 Chores

### Node.js 22 LTS is now required for development

`lint-staged@17` and `eslint-plugin-jsdoc@63` both drop Node 20 in this release; `vite@8` already warned about Node 20 below `20.19`. The minimum supported Node version for running scripts (`yarn dev`, `yarn lint`, husky / lint-staged pre-commit hook) is now Node 22.22.1+ (matches `package.json` `engines.node: ">=22.0.0"`).

**Action:** install or switch to Node 22 LTS (e.g. `nvm install 22 && nvm use 22`) before running `yarn install` or any workspace script.
Loading
Loading