Update
This commit is contained in:
@@ -0,0 +1,221 @@
|
||||
# Architecture
|
||||
|
||||
## Process model
|
||||
|
||||
```text
|
||||
+---------------- Electron renderer ----------------+
|
||||
| Desktop UI |
|
||||
| No Node.js, filesystem, process or token access |
|
||||
+-------------------------+---------------------------+
|
||||
|
|
||||
frozen preload API
|
||||
|
|
||||
+-------------------------v---------------------------+
|
||||
| Electron main process |
|
||||
| |
|
||||
| IPC validation + trusted sender checks |
|
||||
| ConfigStore -------- schema 5 + protected Gitea/SSH secrets |
|
||||
| GitService ----------- Git through execFile args |
|
||||
| GiteaService --------- repositories + Actions API |
|
||||
| RepositoryService ---- discovery + aggregation |
|
||||
| RepositoryMonitor ---- local state awareness |
|
||||
| PreflightService ----- system/deployment readiness |
|
||||
| DeploymentService ---- dispatch/poll/verify |
|
||||
| DiagnosticsService --- JSONL/redaction/support ZIP |
|
||||
+----------------+--------------------+---------------+
|
||||
| |
|
||||
local Git Gitea API
|
||||
| |
|
||||
working trees repositories/actions
|
||||
|
|
||||
trusted runner
|
||||
|
|
||||
fixed allowlisted entry point
|
||||
|
|
||||
app + independent status JSON
|
||||
```
|
||||
|
||||
## Trust boundaries
|
||||
|
||||
### Renderer
|
||||
|
||||
The renderer is untrusted input. It can request only methods exposed by
|
||||
`preload.cjs`. Node integration is disabled, context isolation and sandboxing
|
||||
are enabled, and IPC requests are accepted only from the packaged file origin.
|
||||
Renderer crashes and unhandled rejections are reported through a sanitized
|
||||
one-way diagnostic method.
|
||||
|
||||
### Main process
|
||||
|
||||
Paths, URLs, file selections, branch names, commit messages, diagnostic export
|
||||
modes and deployment requests are checked here. The renderer cannot supply a
|
||||
server command. UI eligibility is advisory; main-process services re-read the
|
||||
working tree and remote ancestry immediately before privileged actions.
|
||||
|
||||
### Gitea
|
||||
|
||||
Gitea supplies repository metadata and the Actions control plane. ForgeFlow
|
||||
handles run-list response variants, retries servers that reject optional query
|
||||
filters and can fall back to the older tasks listing. Requests log only method,
|
||||
API path, status and duration—not authorization headers or request bodies.
|
||||
|
||||
### Runner and server
|
||||
|
||||
The runner consumes only committed trusted workflows. The root-owned server
|
||||
entry point reads an exact repository/environment target from a root-owned,
|
||||
non-writable data file. It validates the full SHA again and uses a
|
||||
per-environment lock. The runner receives no free-form command from ForgeFlow.
|
||||
|
||||
## Local state
|
||||
|
||||
`forgeflow-config.json` lives below Electron's platform-specific user-data path
|
||||
and is written atomically. Schema version 3 contains:
|
||||
|
||||
- Gitea connection metadata and an OS-encrypted token blob where available;
|
||||
- workspace roots and explicit repository mappings;
|
||||
- favorites and application preferences;
|
||||
- diagnostic retention and level preferences;
|
||||
- multiple deployment profiles and last server state;
|
||||
- up to 250 operation records.
|
||||
|
||||
Renderer-visible public state never contains the plaintext or encrypted token.
|
||||
|
||||
Structured diagnostic JSONL files live in a separate `diagnostics` directory.
|
||||
They have independent rotation and retention and never block normal app use when
|
||||
logging itself fails.
|
||||
|
||||
## Repository aggregation
|
||||
|
||||
1. Fetch accessible Gitea repositories.
|
||||
2. Scan bounded workspace roots for Git working trees.
|
||||
3. Normalize HTTPS and SCP-style SSH remotes.
|
||||
4. Match local `origin` identity to `owner/repository`.
|
||||
5. Apply explicit mappings where present.
|
||||
6. Read Git state with bounded concurrency.
|
||||
7. Attach favorites, deployment profiles and last server state.
|
||||
8. Derive attention and ready-to-deploy status.
|
||||
9. Feed linked paths to the repository monitor.
|
||||
|
||||
## Repository clone lifecycle
|
||||
|
||||
The first configured project root is the default. The renderer submits only the
|
||||
current Gitea repository identity and either `default` or `custom` location
|
||||
mode. The main process resolves the repository again, selects a configured root
|
||||
or a native-dialog result, calculates the repository-named child path and asks
|
||||
GitService to inspect it.
|
||||
|
||||
```text
|
||||
repository identity
|
||||
|
|
||||
current Gitea metadata
|
||||
|
|
||||
project root + safe repository folder name
|
||||
|
|
||||
missing / empty / matching checkout / conflict
|
||||
|
|
||||
clone or reuse -> save mapping -> refresh -> monitor
|
||||
```
|
||||
|
||||
A matching existing checkout is reused. Different repositories and arbitrary
|
||||
non-empty folders are rejected.
|
||||
|
||||
## Git execution
|
||||
|
||||
ForgeFlow invokes the installed Git executable through `execFile`; it never
|
||||
builds shell command strings. File arguments must remain repository-relative
|
||||
and cannot contain traversal segments.
|
||||
|
||||
Core status command:
|
||||
|
||||
```bash
|
||||
git status --porcelain=v2 --branch -z --untracked-files=all
|
||||
```
|
||||
|
||||
Synchronization is intentionally limited to:
|
||||
|
||||
```bash
|
||||
git pull --ff-only
|
||||
```
|
||||
|
||||
Branch switching requires a clean working tree. Stash supports untracked files.
|
||||
Deployment and rollback verify the full SHA against `origin/<allowed-branch>`
|
||||
with `merge-base --is-ancestor`.
|
||||
|
||||
## Preflight model
|
||||
|
||||
### System preflight
|
||||
|
||||
Checks Git, author identity, app storage, diagnostic storage, OS credential
|
||||
protection, configured workspace roots and—when credentials are present—Gitea
|
||||
connectivity and repository visibility.
|
||||
|
||||
### Deployment preflight
|
||||
|
||||
Checks repository link, Git working tree, allowed branch, clean state, upstream,
|
||||
ahead/behind state, exact remote SHA, local and remote workflow presence,
|
||||
Actions API access, server status endpoint and healthcheck.
|
||||
|
||||
Only failed required checks block readiness. The deployment backend repeats
|
||||
safety-critical Git/SHA validation after the user continues.
|
||||
|
||||
## Repository monitor
|
||||
|
||||
The current monitor periodically fingerprints Git state. It establishes a
|
||||
baseline, reports later changes and pauses during mutating operations to avoid
|
||||
intermediate noise. It is dependency-free rather than a native filesystem
|
||||
watcher.
|
||||
|
||||
## Deployment lifecycle
|
||||
|
||||
```text
|
||||
requested -> queued -> running -> health/version verification -> terminal
|
||||
```
|
||||
|
||||
A deployment operation stores the exact SHA, fixed profile, environment,
|
||||
workflow and a UUID request ID. Polling then:
|
||||
|
||||
1. finds the matching Actions run by SHA, branch, workflow and dispatch time;
|
||||
2. normalizes run status;
|
||||
3. retrieves jobs and locally redacted runner output;
|
||||
4. maps jobs to ForgeFlow stages;
|
||||
5. reads the independent status endpoint and healthcheck after runner success;
|
||||
6. verifies live SHA equality;
|
||||
7. stores success, rolled-back, failed or cancelled.
|
||||
|
||||
The request ID is sent to the workflow and server status document, making one
|
||||
operation correlatable without using a credential as an identifier.
|
||||
|
||||
## Diagnostics pipeline
|
||||
|
||||
```text
|
||||
event -> recursive sanitization -> ordered JSONL write
|
||||
|
|
||||
support export requested
|
||||
|
|
||||
fresh state + preflight + redacted logs
|
||||
|
|
||||
strict/standard privacy transformation
|
||||
|
|
||||
fail-closed local secret safety audit
|
||||
|
|
||||
ZIP + SHA-256 result
|
||||
```
|
||||
|
||||
Raw runner output is deliberately omitted from exported support bundles.
|
||||
|
||||
## Status endpoint
|
||||
|
||||
The recommended endpoint is a static JSON file served independently from the
|
||||
application. It reports live, previous and requested SHAs, request ID, health
|
||||
and last exit code. See `STATUS_ENDPOINT.md`.
|
||||
|
||||
|
||||
## v0.4 services
|
||||
|
||||
- `UpdateService` reads `package.json` at an exact Gitea branch SHA, downloads an
|
||||
authenticated archive and launches the rollback-capable Windows source updater.
|
||||
- `SshService` provides pinned-host SSH execution with encrypted password or
|
||||
private-key passphrase storage.
|
||||
- `UnraidDeploymentService` inspects existing application folders and performs
|
||||
exact-SHA Git and Docker Compose deployments without deleting untracked
|
||||
runtime data.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Deployment setup guide
|
||||
|
||||
This guide connects one Gitea repository to one server environment without giving the desktop arbitrary shell access.
|
||||
|
||||
## 1. Add fixed workflows
|
||||
|
||||
Copy these examples into the repository:
|
||||
|
||||
```text
|
||||
examples/gitea-actions/deploy.yml -> .gitea/workflows/deploy.yml
|
||||
examples/gitea-actions/rollback.yml -> .gitea/workflows/rollback.yml
|
||||
```
|
||||
|
||||
Change the runner label to the label registered for the target environment.
|
||||
|
||||
## 2. Install the allowlisted server entry point
|
||||
|
||||
Copy `examples/server/forgeflow-deploy` to `/usr/local/bin/forgeflow-deploy`, customize its repository/environment allowlist and make it root-owned:
|
||||
|
||||
```bash
|
||||
sudo install -o root -g root -m 0755 forgeflow-deploy /usr/local/bin/forgeflow-deploy
|
||||
```
|
||||
|
||||
Grant the runner account permission to execute only this entry point where elevation is needed. Do not grant unrestricted shell or Docker administration merely for ForgeFlow.
|
||||
|
||||
## 3. Expose deployment status
|
||||
|
||||
The example script writes an atomic JSON document beneath `/var/lib/forgeflow-status`. Serve the appropriate file at a fixed HTTPS URL, for example with `examples/server/nginx-forgeflow-status.conf`.
|
||||
|
||||
See `STATUS_ENDPOINT.md` for the contract.
|
||||
|
||||
## 4. Configure the ForgeFlow profile
|
||||
|
||||
Open the repository, choose **Deployments** and add an environment with:
|
||||
|
||||
- Name: `Production` or `Staging`.
|
||||
- Environment: the fixed workflow input.
|
||||
- Branch: usually `main`.
|
||||
- Workflow file: `deploy.yml`.
|
||||
- Rollback workflow: `rollback.yml`.
|
||||
- Status URL: the JSON endpoint.
|
||||
- Healthcheck URL: the application health endpoint.
|
||||
- Confirmation: enabled for production.
|
||||
|
||||
## 5. Validate the complete path
|
||||
|
||||
Test these scenarios before relying on production:
|
||||
|
||||
1. Clean commit and push.
|
||||
2. Successful deployment to the exact SHA.
|
||||
3. Gitea runner failure.
|
||||
4. Application healthcheck failure.
|
||||
5. Server reports the wrong SHA.
|
||||
6. Second deployment while the lock is held.
|
||||
7. Rollback to the recorded previous SHA.
|
||||
8. Token without sufficient permissions.
|
||||
|
||||
Keep a manual recovery path documented even after rollback works.
|
||||
@@ -0,0 +1,150 @@
|
||||
# Diagnostics, privacy and support bundles
|
||||
|
||||
ForgeFlow v0.3.2 records development-oriented diagnostics locally so failures
|
||||
can be investigated without requesting the user's Gitea token, SSH key or
|
||||
server password.
|
||||
|
||||
## Storage
|
||||
|
||||
Diagnostic events are stored beneath the Electron application-data directory in:
|
||||
|
||||
```text
|
||||
diagnostics/forgeflow-YYYY-MM-DD.jsonl
|
||||
```
|
||||
|
||||
The Diagnostics page displays an aliased path such as `<HOME>` rather than the
|
||||
Windows account name. Files use restrictive permissions where the operating
|
||||
system supports them.
|
||||
|
||||
Defaults:
|
||||
|
||||
- enabled;
|
||||
- minimum level `info`;
|
||||
- 14-day retention;
|
||||
- 8 MB maximum per log segment;
|
||||
- daily filenames with numbered rotation;
|
||||
- ordered asynchronous writes;
|
||||
- no application crash when diagnostic storage itself fails.
|
||||
|
||||
These values can be changed in **Diagnostics -> Recording policy**.
|
||||
|
||||
## What an event can contain
|
||||
|
||||
Useful fields include:
|
||||
|
||||
- UTC timestamp;
|
||||
- level and stable event name;
|
||||
- per-launch session identifier;
|
||||
- operation or deployment request identifier;
|
||||
- Git/Gitea operation outcome;
|
||||
- HTTP status, duration and endpoint path without request headers;
|
||||
- repository state and branch/SHA metadata;
|
||||
- preflight result;
|
||||
- sanitized exception name, code, message and stack;
|
||||
- renderer crash or unhandled-rejection metadata.
|
||||
|
||||
ForgeFlow does not log IPC payloads, request authorization headers or Gitea
|
||||
response bodies merely because a request was made.
|
||||
|
||||
## Redaction
|
||||
|
||||
Every event passes through a recursive sanitizer before it is written.
|
||||
Redaction covers:
|
||||
|
||||
- the currently active Gitea token;
|
||||
- token, password, authorization, credential, API-key, client-secret and
|
||||
encrypted-token object fields, including camelCase variants;
|
||||
- bearer/token/basic authorization values in strings;
|
||||
- common token query parameters;
|
||||
- credentials embedded in URLs;
|
||||
- PEM private-key blocks;
|
||||
- known Gitea/Git hosting token patterns;
|
||||
- Windows, macOS and Linux home-directory paths;
|
||||
- application source path aliases;
|
||||
- circular data structures and oversized strings.
|
||||
|
||||
Credential values are replaced with `[REDACTED]`; user paths use aliases such as
|
||||
`<HOME>`.
|
||||
|
||||
## Support bundle
|
||||
|
||||
**Create diagnostic ZIP** exports a local archive containing:
|
||||
|
||||
```text
|
||||
manifest.json
|
||||
safety-audit.json
|
||||
README.txt
|
||||
system.json
|
||||
diagnostics-status.json
|
||||
configuration-sanitized.json
|
||||
repositories-sanitized.json
|
||||
operations-sanitized.json
|
||||
preflight.json
|
||||
context.json
|
||||
logs/*.jsonl
|
||||
```
|
||||
|
||||
The application returns the SHA-256 of the generated archive so a shared file
|
||||
can be identified exactly.
|
||||
|
||||
### Excluded data
|
||||
|
||||
The bundle intentionally excludes:
|
||||
|
||||
- plaintext Gitea access tokens;
|
||||
- Electron `safeStorage` encrypted-token blobs;
|
||||
- request authorization headers;
|
||||
- passwords and private keys;
|
||||
- raw Gitea runner logs;
|
||||
- arbitrary environment-variable dumps;
|
||||
- full local file contents and Git diffs.
|
||||
|
||||
ForgeFlow does not automatically ingest or persist raw runner output. Job names,
|
||||
statuses and safe operation summaries are stored locally; full runner output remains
|
||||
available only in the trusted Gitea Actions interface when deeper server-side
|
||||
investigation is necessary.
|
||||
|
||||
## Privacy modes
|
||||
|
||||
### Standard
|
||||
|
||||
Preserves repository names and user-facing identifiers. Local home paths and
|
||||
credentials are still redacted. Use when the recipient already knows the
|
||||
project context.
|
||||
|
||||
### Strict
|
||||
|
||||
Additionally replaces repository and user identifiers with deterministic
|
||||
SHA-256-based aliases. Related events remain correlatable without revealing the
|
||||
original names.
|
||||
|
||||
## Fail-closed bundle audit
|
||||
|
||||
Immediately before writing the archive, ForgeFlow scans every prepared entry
|
||||
for:
|
||||
|
||||
- the known active runtime secret values;
|
||||
- private-key begin markers;
|
||||
- unredacted credentials embedded in HTTP(S) URLs.
|
||||
|
||||
The result is stored as `safety-audit.json`. When a finding remains, archive
|
||||
creation is aborted and the unsafe ZIP is not written.
|
||||
|
||||
## Practical limitation
|
||||
|
||||
No generic logger can mathematically identify every unknown secret if a third-
|
||||
party process prints an arbitrary value without a label or recognizable format.
|
||||
ForgeFlow reduces this risk by not including raw runner logs, not recording IPC
|
||||
payloads and applying both structured and textual redaction. Always inspect a
|
||||
support bundle before sharing it, particularly when custom integrations have
|
||||
been added.
|
||||
|
||||
## Development workflow after a failure
|
||||
|
||||
1. Reproduce the issue once when safe.
|
||||
2. Note the approximate time and repository/environment.
|
||||
3. Run the relevant preflight.
|
||||
4. Export a Strict diagnostic bundle.
|
||||
5. Keep the returned SHA-256 with the bug report.
|
||||
6. Describe the visible action that failed.
|
||||
7. Share no separate token, key or password.
|
||||
@@ -0,0 +1,147 @@
|
||||
# LumaOps server versus Gitea audit
|
||||
|
||||
This audit compares the supplied `lumaops_server.zip` and `LumaOps_gitea.zip`.
|
||||
|
||||
## Main result
|
||||
|
||||
The main Unraid working tree and the supplied Gitea checkout point to exactly the same commit:
|
||||
|
||||
```text
|
||||
d42d4a7f08240c478d07466e3fabec654dc71367
|
||||
```
|
||||
|
||||
Latest subject:
|
||||
|
||||
```text
|
||||
Preserve colors across Aura zone updates
|
||||
```
|
||||
|
||||
There is therefore no source-version drift at the root of the live LumaOps folder.
|
||||
|
||||
## Root Git repository
|
||||
|
||||
The root `.git` directory should remain in place. It enables:
|
||||
|
||||
- exact-SHA verification;
|
||||
- controlled fetch and reset;
|
||||
- a reliable previous-version reference;
|
||||
- rollback without copying a second complete source tree.
|
||||
|
||||
The archived server copy showed one root status difference for `scripts/unraid-hardware-setup.sh`: file mode `100755 → 100644`. This is consistent with Unix executable bits being lost during ZIP handling. The file content did not differ. Check the executable bit directly on Unraid before deployment.
|
||||
|
||||
|
||||
## Origin URL mismatch to resolve
|
||||
|
||||
The supplied server root uses:
|
||||
|
||||
```text
|
||||
ssh://git@127.0.0.1:222/NuklearRabbit/LumaOps.git
|
||||
```
|
||||
|
||||
The supplied Gitea checkout uses:
|
||||
|
||||
```text
|
||||
https://gitea.itworx.tech/Jens/LumaOps.git
|
||||
```
|
||||
|
||||
Although both archives currently point to the same commit, these are different
|
||||
repository paths. Before the first ForgeFlow deployment, choose the server-
|
||||
reachable URL for the authoritative `Jens/LumaOps` repository, for example an
|
||||
SSH URL through `127.0.0.1:222` when Gitea runs on the same Unraid host.
|
||||
|
||||
ForgeFlow 0.4 detects this mismatch. Deployment is blocked unless the profile
|
||||
matches the existing origin or **Align an existing server origin to this URL**
|
||||
is explicitly enabled.
|
||||
|
||||
## Runtime and persistent paths
|
||||
|
||||
The server copy contains runtime data that must not be replaced by source updates:
|
||||
|
||||
- `appdata/`
|
||||
- `data/`
|
||||
- `logs/`
|
||||
- `.env` and application-specific configuration
|
||||
|
||||
The repository `.gitignore` already excludes the principal runtime paths. ForgeFlow's SSH strategy uses Git reset without `git clean`, so untracked persistent data remains in place.
|
||||
|
||||
## Compose and Unraid integration
|
||||
|
||||
The root `docker-compose.yml` is already suitable as the authoritative deployment definition. It includes:
|
||||
|
||||
- build context at the project root;
|
||||
- container name `lumaops`;
|
||||
- the Unraid `dockerman` label;
|
||||
- a Web UI label;
|
||||
- an Unraid icon label;
|
||||
- `${WEB_PORT:-1223}:${APP_PORT:-8080}`;
|
||||
- persistent relative volumes;
|
||||
- USB, HID and I²C devices;
|
||||
- a healthcheck.
|
||||
|
||||
ForgeFlow should use this existing Compose file rather than generate a replacement. Ports and complex device mappings belong in the repository's maintained Compose definition.
|
||||
|
||||
The supplied `.dockerignore` already excludes `.git`, so keeping the root Git
|
||||
working tree does **not** copy Git history into the Docker build context. It does
|
||||
not yet explicitly exclude the existing runtime/legacy folders `appdata/`,
|
||||
`data/`, `logs/` and `source/`. Before the first production rebuild, add the
|
||||
paths that are not build inputs:
|
||||
|
||||
```text
|
||||
appdata/
|
||||
data/
|
||||
logs/
|
||||
source/
|
||||
.forgeflow/
|
||||
```
|
||||
|
||||
ForgeFlow 0.4 detects existing preserved paths and nested Git repositories that
|
||||
are missing from `.dockerignore` and reports them as a preflight warning. The
|
||||
tool does not silently edit a source-controlled `.dockerignore`; the correction
|
||||
should be committed to Gitea so every deployment uses the same build context.
|
||||
|
||||
## Nested `source/` repository
|
||||
|
||||
The server archive also contains a nested Git working tree under:
|
||||
|
||||
```text
|
||||
source/
|
||||
```
|
||||
|
||||
Its HEAD is:
|
||||
|
||||
```text
|
||||
b746a52af1613f4291235f5e8165b8197a269a79
|
||||
```
|
||||
|
||||
It was ahead of its own upstream and included rebase metadata in the supplied archive. The root Compose file uses build context `.` and does not reference `source/`. This strongly indicates that `source/` is an abandoned or historical checkout rather than the active deployment source.
|
||||
|
||||
ForgeFlow reports this as a nested-repository warning and does not remove it automatically.
|
||||
|
||||
Recommended migration:
|
||||
|
||||
1. Back up `/mnt/user/appdata/lumaops`.
|
||||
2. Verify on Unraid that `docker compose config` uses the root project.
|
||||
3. Stop changing files in `source/`.
|
||||
4. Rename it temporarily to `source.legacy-backup`.
|
||||
5. Rebuild and test LumaOps from the root.
|
||||
6. Remove the legacy copy only after a successful validation period.
|
||||
|
||||
Do not delete the root `.git` directory. Also do not delete the nested `source/`
|
||||
directory as part of the first ForgeFlow test. Treat its cleanup as a separate,
|
||||
backed-up migration after the root deployment and rollback have both been
|
||||
validated.
|
||||
|
||||
## Recommended ForgeFlow profile
|
||||
|
||||
```text
|
||||
Provider: SSH / Unraid
|
||||
Server folder: lumaops
|
||||
Branch: main
|
||||
Compose mode: Repository/server Compose
|
||||
Compose file: docker-compose.yml
|
||||
Clone URL: the Git URL reachable from Unraid
|
||||
Healthcheck: the existing LumaOps health URL, when exposed
|
||||
Preserve paths: .env, appdata, data, logs, config, compose.override.yml
|
||||
```
|
||||
|
||||
No folder rename is required for LumaOps because `lumaops` already aligns with the repository name.
|
||||
@@ -0,0 +1,32 @@
|
||||
# ForgeFlow 0.2.0 release notes
|
||||
|
||||
ForgeFlow 0.2.0 turns the original visual prototype into a substantially more operational personal release cockpit.
|
||||
|
||||
## Highlights
|
||||
|
||||
- Automatic repository status monitoring with safe pause/resume around Git mutations.
|
||||
- Commit-only and commit-and-push flows with recoverable push failures.
|
||||
- Branch creation, switching, publication and stash workflows.
|
||||
- Favorite repositories and action-oriented attention queues.
|
||||
- Multiple deployment environments per repository.
|
||||
- Exact remote-branch SHA verification before deploy and rollback.
|
||||
- Gitea Actions run, job and available log polling.
|
||||
- Live server version, previous version and health verification.
|
||||
- Fixed-workflow rollback to a recorded full commit SHA.
|
||||
- Stronger IPC, URL, path and secret-handling controls.
|
||||
- Reworked renderer with command palette and live deployment states.
|
||||
- 21 passing automated tests, including real temporary Git remotes.
|
||||
- Headless browser smoke coverage at three desktop viewport sizes.
|
||||
|
||||
## Upgrade notes
|
||||
|
||||
Configuration is migrated automatically to schema version 2. Existing Gitea tokens are preserved when the settings form is saved with an empty token field.
|
||||
|
||||
Deployment profiles now support independent branch, workflow, rollback workflow, healthcheck and status endpoint settings. Review existing profiles before using them against production.
|
||||
|
||||
## Known limitations
|
||||
|
||||
- No signed installer or automatic update channel is included in this source release.
|
||||
- Partial-hunk staging, conflict resolution and protected-branch awareness are not yet implemented.
|
||||
- Gitea Actions behavior still needs acceptance testing against the intended Gitea and act_runner versions.
|
||||
- Native desktop notifications, tray mode and accessibility acceptance remain future work.
|
||||
@@ -0,0 +1,140 @@
|
||||
# ForgeFlow 0.3.0 release notes
|
||||
|
||||
Release date: 2026-07-24
|
||||
Release type: self-service test release
|
||||
|
||||
## Goal
|
||||
|
||||
Version 0.3.0 closes the gap between a functional developer preview and a build
|
||||
that can be configured and tested by its owner without sharing credentials with
|
||||
a developer. The release concentrates on setup guidance, deterministic
|
||||
preflight checks, safe diagnostics and server-side allowlisting.
|
||||
|
||||
## Setup and readiness
|
||||
|
||||
- Replaced the lightweight onboarding with a five-step setup wizard.
|
||||
- Added a computer readiness preflight for Git, Git identity, writable app data,
|
||||
writable diagnostics and OS credential encryption.
|
||||
- Added a Gitea validation stage before setup completion.
|
||||
- Added visible repository discovery results.
|
||||
- Added safe setup diagnostics before Gitea is connected.
|
||||
- Added a comprehensive start page and end-to-end setup guide.
|
||||
- Added a JSON-capable command-line doctor for local environment validation.
|
||||
|
||||
## Deployment preflight
|
||||
|
||||
A deployment now receives a visible preflight before confirmation and a second
|
||||
mandatory backend validation immediately before dispatch. Checks include:
|
||||
|
||||
- linked local Git repository;
|
||||
- allowed deployment branch;
|
||||
- clean working tree;
|
||||
- configured upstream;
|
||||
- local/remote ahead and behind state;
|
||||
- exact full SHA on the remote branch;
|
||||
- local deploy and rollback workflow files;
|
||||
- remote workflow visibility through Gitea;
|
||||
- Gitea Actions API availability;
|
||||
- deployment status endpoint;
|
||||
- application health endpoint.
|
||||
|
||||
Optional environment checks can warn without hiding required failures.
|
||||
Deployment cannot bypass the mandatory checks through the renderer.
|
||||
|
||||
## Diagnostic logging
|
||||
|
||||
- Added ordered structured JSONL logging in the Electron app-data directory.
|
||||
- Added daily files, size rotation and retention pruning.
|
||||
- Added configurable logging level, retention and file-size policy.
|
||||
- Added process, renderer, Git, repository, Gitea, IPC, preflight and deployment
|
||||
diagnostics.
|
||||
- Added per-launch session IDs and per-operation deployment request IDs.
|
||||
- Added a no-throw logging design so diagnostic storage does not crash the app.
|
||||
- Added local clear and open-folder controls.
|
||||
|
||||
## Secret and privacy protection
|
||||
|
||||
- Added recursive sensitive-key detection, including camelCase variants.
|
||||
- Added bearer/basic/token/password/API-key/client-secret redaction.
|
||||
- Added runtime-secret replacement.
|
||||
- Added URL credential, token query parameter and private-key redaction.
|
||||
- Added common hosting-token pattern redaction.
|
||||
- Added user-home and source-root path aliases.
|
||||
- Added strict privacy mode with deterministic identifier hashing.
|
||||
- Stopped automatically ingesting or persisting raw runner logs; full output stays in Gitea.
|
||||
- Added fail-closed bundle auditing before the ZIP is written.
|
||||
- Added SHA-256 output for every generated support bundle.
|
||||
|
||||
No Gitea token, SSH key or server password is needed by the developer to use
|
||||
these diagnostics.
|
||||
|
||||
## Support bundle contents
|
||||
|
||||
A support bundle can contain:
|
||||
|
||||
- manifest and safety audit;
|
||||
- system and application version information;
|
||||
- sanitized public configuration;
|
||||
- sanitized repository state;
|
||||
- sanitized operation history;
|
||||
- latest preflight report;
|
||||
- safe diagnostic status;
|
||||
- redacted JSONL logs.
|
||||
|
||||
It intentionally excludes protected token blobs, authorization headers,
|
||||
private keys, source files, Git diffs, environment dumps and raw runner output.
|
||||
|
||||
## Server deployment hardening
|
||||
|
||||
- Moved target definitions to a root-owned `/etc/forgeflow/targets.conf` file.
|
||||
- Added exact repository/environment allowlisting.
|
||||
- Made the server status URL mandatory and require matching SHA plus request ID before success.
|
||||
- Added configuration ownership and permission checks.
|
||||
- Added absolute and restricted path validation.
|
||||
- Added exact remote-SHA and branch ancestry validation.
|
||||
- Added per-target `flock` locking.
|
||||
- Added Docker Compose result and health verification.
|
||||
- Added current, previous, requested SHA, request ID and exit code to server
|
||||
status output.
|
||||
- Added a restrictive sudoers template for the runner.
|
||||
- Added explicit deploy and rollback workflow request-ID inputs.
|
||||
- Added backend repository re-resolution so renderer-supplied paths and identities
|
||||
cannot select an arbitrary local folder or Gitea repository.
|
||||
- Captured pre-dispatch Actions run IDs so polling cannot attach to an older run
|
||||
with the same commit SHA.
|
||||
- Required repository, environment, live SHA, requested SHA, request ID, zero
|
||||
server exit code and explicit health success before marking a release complete.
|
||||
- Restricted rollback to the exact previous SHA currently reported by the server
|
||||
status endpoint.
|
||||
|
||||
## User interface
|
||||
|
||||
- Added a dedicated Diagnostics workspace.
|
||||
- Added system and deployment preflight presentation.
|
||||
- Added diagnostic policy controls.
|
||||
- Added Standard and Strict support-bundle export.
|
||||
- Added support-bundle checksum and reveal action.
|
||||
- Added readiness explanations to onboarding.
|
||||
- Replaced duplicate sidebar navigation with a compact safe-diagnostics state.
|
||||
|
||||
## Validation
|
||||
|
||||
- 39 required project files validated.
|
||||
- 35 JavaScript files passed syntax checks.
|
||||
- 36 of 36 automated tests passed.
|
||||
- Two real temporary Git remotes remain part of the integration suite.
|
||||
- New tests cover redaction, diagnostic rotation/export, support ZIP generation,
|
||||
fail-closed safety auditing, preflight and Gitea workflow-file checks.
|
||||
|
||||
## Known boundaries
|
||||
|
||||
- The release is not code-signed.
|
||||
- A platform-native installer is not guaranteed by the source ZIP alone.
|
||||
- The private Gitea, runner and server environment still requires the documented
|
||||
local acceptance test.
|
||||
- Application-specific compose commands and health endpoints remain target
|
||||
configuration, because they cannot be inferred safely.
|
||||
- No redactor can mathematically identify an arbitrary unknown secret printed by
|
||||
custom third-party code; raw runner logs therefore remain only in the trusted
|
||||
Gitea Actions interface, and exported bundles should still be inspected before
|
||||
sharing.
|
||||
@@ -0,0 +1,25 @@
|
||||
# ForgeFlow 0.3.1 release notes
|
||||
|
||||
## Windows environment-doctor hotfix
|
||||
|
||||
Version 0.3.1 fixes a Windows-only false negative in the environment doctor.
|
||||
The setup script could invoke npm successfully, install all dependencies and then
|
||||
report `spawn npm ENOENT` from Node.js. Windows exposes npm through a command
|
||||
shim (`npm.cmd`), which cannot always be executed directly through
|
||||
`child_process.execFile`.
|
||||
|
||||
The doctor now:
|
||||
|
||||
- uses `npm_execpath` through the active Node executable when launched by npm;
|
||||
- falls back to `cmd.exe /c npm --version` on Windows;
|
||||
- continues to invoke npm directly on Linux and macOS;
|
||||
- reports which safe invocation path succeeded;
|
||||
- reads its displayed application version from `package.json` instead of a
|
||||
duplicated hard-coded value.
|
||||
|
||||
Three regression tests cover npm-script execution, the Windows command-shim
|
||||
fallback and the normal non-Windows path.
|
||||
|
||||
The npm deprecation messages printed during dependency installation are warnings
|
||||
from transitive build-tool dependencies. They were not the cause of the setup
|
||||
failure and do not prevent ForgeFlow from starting.
|
||||
@@ -0,0 +1,72 @@
|
||||
# ForgeFlow 0.3.2 release notes
|
||||
|
||||
## Automatic clone destinations
|
||||
|
||||
The normal **Clone from Gitea** action no longer opens a Windows folder picker
|
||||
for every repository. ForgeFlow now:
|
||||
|
||||
1. uses the first configured project root as the default;
|
||||
2. derives a safe folder name from the repository clone URL;
|
||||
3. creates `<project-root>/<repository-name>`;
|
||||
4. clones into that folder;
|
||||
5. validates the resulting Git repository;
|
||||
6. saves the repository mapping;
|
||||
7. starts monitoring the working tree;
|
||||
8. opens the linked repository in ForgeFlow.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
Default project root: C:\Users\Jens\Projects
|
||||
Gitea repository: Jens/Portfolio
|
||||
Automatic target: C:\Users\Jens\Projects\Portfolio
|
||||
```
|
||||
|
||||
A separate **Choose another location** action remains available for exceptional
|
||||
cases. That choice selects a parent project root; ForgeFlow still creates the
|
||||
repository-named subfolder itself.
|
||||
|
||||
## Existing-folder safety
|
||||
|
||||
The clone backend now inspects the automatic target before running Git:
|
||||
|
||||
- a missing target is created through `git clone`;
|
||||
- an existing empty directory is accepted;
|
||||
- an existing Git checkout with the same normalized origin is linked;
|
||||
- a different Git repository is blocked;
|
||||
- an ordinary non-empty directory is blocked;
|
||||
- a file at the target path is blocked.
|
||||
|
||||
ForgeFlow never silently overwrites a conflicting folder and does not create a
|
||||
duplicated `Repository\Repository` directory.
|
||||
|
||||
## Security and consistency
|
||||
|
||||
The renderer no longer supplies a free-form remote URL or clone destination to
|
||||
the privileged Git operation. It sends the Gitea repository identity and a
|
||||
location mode. The main process then:
|
||||
|
||||
- resolves the current repository again from Gitea;
|
||||
- selects the configured root or a native-dialog result;
|
||||
- calculates the destination itself;
|
||||
- performs conflict checks;
|
||||
- clones or reuses the checkout;
|
||||
- persists the mapping atomically.
|
||||
|
||||
Clone diagnostics contain repository identity, target, branch and commit state,
|
||||
but no Gitea token or authorization header.
|
||||
|
||||
## Validation
|
||||
|
||||
Version 0.3.2 contains 45 passing automated tests. New coverage includes:
|
||||
|
||||
- HTTPS and SSH repository folder-name derivation;
|
||||
- automatic target construction;
|
||||
- missing and empty target handling;
|
||||
- same-origin checkout reuse;
|
||||
- different-repository rejection;
|
||||
- non-empty ordinary-folder rejection;
|
||||
- file-at-target rejection.
|
||||
|
||||
Existing Git, deployment, diagnostics, redaction, rollback and Windows doctor
|
||||
tests continue to pass.
|
||||
@@ -0,0 +1,57 @@
|
||||
# ForgeFlow 0.4.0 release notes
|
||||
|
||||
## Scrollable change list
|
||||
|
||||
The changed-file panel now has an independent bounded vertical scroll area. Large commits no longer make lower files unreachable.
|
||||
|
||||
## Commit readiness
|
||||
|
||||
The action panel now labels the commit message as required and displays the exact reason why commit actions are disabled. Selected files are staged automatically during commit; manual staging remains available as an optional index-review step.
|
||||
|
||||
## ITWorx.tech branding
|
||||
|
||||
The supplied ITWorx.tech logo is integrated into the title bar, first-run setup and application icons.
|
||||
|
||||
## Built-in source updater
|
||||
|
||||
ForgeFlow can check the configured private Gitea repository, defaulting to `Jens/ForgeFlow` on `main`.
|
||||
|
||||
The updater:
|
||||
|
||||
- reads the remote `package.json` at an exact branch commit;
|
||||
- compares semantic versions;
|
||||
- downloads an authenticated exact-SHA archive;
|
||||
- verifies a SHA-256 checksum;
|
||||
- closes ForgeFlow;
|
||||
- backs up the current source;
|
||||
- installs dependencies;
|
||||
- runs the complete quality gate;
|
||||
- restores the previous source when validation fails;
|
||||
- restarts ForgeFlow.
|
||||
|
||||
## SSH / Unraid deployment
|
||||
|
||||
A server can be configured once with hostname, SSH port, username, encrypted credentials and `/mnt/user/appdata` as base path.
|
||||
|
||||
Deployment profiles support:
|
||||
|
||||
- existing Git-backed application folders;
|
||||
- automatic new folder creation;
|
||||
- exact commit verification;
|
||||
- pinned SSH host identity;
|
||||
- existing or generated Compose configuration;
|
||||
- host and container ports;
|
||||
- Unraid Web UI and icon labels;
|
||||
- server-folder mapping;
|
||||
- tracked-change blocking;
|
||||
- nested-Git warnings;
|
||||
- runtime-data preservation;
|
||||
- rollback to the previous SHA.
|
||||
|
||||
## LumaOps audit
|
||||
|
||||
The supplied server and Gitea roots both match commit `d42d4a7f08240c478d07466e3fabec654dc71367`. The root Git checkout and Compose file should remain. A stale nested `source/` Git checkout is documented for controlled cleanup.
|
||||
|
||||
## Validation
|
||||
|
||||
ForgeFlow 0.4.0 has 59 passing automated tests, including real temporary Git remotes, update exact-SHA checks, SSH path safety, renderer workflow contracts, diagnostics redaction, exact previous-SHA rollback enforcement and deployment controls.
|
||||
@@ -0,0 +1,26 @@
|
||||
# ForgeFlow 0.4.1 release notes
|
||||
|
||||
## Windows Bash path fix
|
||||
|
||||
ForgeFlow 0.4.1 fixes the source quality gate on Windows when the project is stored at a path such as `C:\Projects\ForgeFlow`.
|
||||
|
||||
The previous verifier passed an absolute Windows path directly to `bash -n`. Bash interpreted the backslashes as escape characters, producing a collapsed path such as `C:ProjectsForgeFlow...` and a false validation failure.
|
||||
|
||||
The verifier now starts Bash with the ForgeFlow project root as its working directory and passes the deployment example as a relative POSIX path:
|
||||
|
||||
```text
|
||||
examples/server/forgeflow-deploy
|
||||
```
|
||||
|
||||
This keeps the project root separate from the script argument and works across Windows Git Bash, Linux and macOS.
|
||||
|
||||
## Regression coverage
|
||||
|
||||
New automated coverage verifies that:
|
||||
|
||||
- a Windows project root remains in `cwd`;
|
||||
- no drive letter or backslash is passed as the Bash script argument;
|
||||
- absolute and escaping script paths are rejected;
|
||||
- Bash validation succeeds from a project root containing spaces.
|
||||
|
||||
No Gitea token, repository mapping, SSH credential, deployment profile or diagnostic history is changed by this update.
|
||||
@@ -0,0 +1,29 @@
|
||||
# ForgeFlow 0.4.2
|
||||
|
||||
## Windows Git Bash reliability hotfix
|
||||
|
||||
This release fixes the two remaining Windows-only failures, including the temporary-directory lock seen during cleanup while validating the 0.4.1 recovery update.
|
||||
|
||||
### Remote shell transport
|
||||
|
||||
SSH / Unraid scripts are now sent through a single-line base64 transport and decoded by Bash on the server. This removes nested quote parsing from the transport layer and prevents Git Bash from misreading multiline commands, single quotes, or newline-stripping expressions.
|
||||
|
||||
The generated command contains no raw multiline payload. The decoded script still enables strict shell mode, disables interactive Git prompts, and requires batch-mode SSH for server-side Git operations.
|
||||
|
||||
### Temporary-directory lock cleanup
|
||||
|
||||
The Bash syntax regression test now retries cleanup when Windows briefly retains a working-directory handle after `bash -n` exits. A successful syntax validation is no longer reported as failed solely because of a short-lived `EBUSY`, `EPERM`, or `ENOTEMPTY` cleanup condition.
|
||||
|
||||
### Additional correction
|
||||
|
||||
The remote status reader now invokes `base64` with the status filename in the correct argument position before stripping CR/LF characters.
|
||||
|
||||
## Regression coverage
|
||||
|
||||
Coverage verifies:
|
||||
|
||||
- Windows Git Bash execution from a project root containing spaces;
|
||||
- a single-line base64 transport for generated Unraid inspection commands;
|
||||
- preserved runtime-path inspection without nested quoting failures;
|
||||
- strict, non-interactive server-side Git settings after decoding;
|
||||
- safe rollback to ForgeFlow 0.4.0 when an update validation fails.
|
||||
@@ -0,0 +1,9 @@
|
||||
# ForgeFlow 0.4.3
|
||||
|
||||
## Full clean release
|
||||
|
||||
- Replaced the OS-dependent local Bash/Windows-temp-path Unraid inspection test with a platform-independent mocked SSH inspection contract.
|
||||
- The SSH inspection command is still verified to use Base64 transport and the returned Unraid metadata is parsed and evaluated deterministically.
|
||||
- Removed the false Windows failure where a local temporary path was interpreted as a remote Linux path.
|
||||
- Regression coverage confirms preserved runtime paths, nested Git directories, `.dockerignore` handling, and remote target resolution.
|
||||
- This release is distributed as a complete source package rather than another incremental updater.
|
||||
@@ -0,0 +1,95 @@
|
||||
# ForgeFlow roadmap
|
||||
|
||||
## Delivered through v0.4
|
||||
|
||||
- coherent Local -> Gitea -> Server desktop model;
|
||||
- protected Gitea credential storage and strict IPC boundary;
|
||||
- real Git status, diff, stage, commit, push, fetch and fast-forward pull;
|
||||
- branches, stashes, favorites and automatic local awareness;
|
||||
- multiple Gitea Actions and SSH / Unraid deployment profiles;
|
||||
- exact-SHA remote-branch validation, runner polling, request-ID verification, health and rollback;
|
||||
- five-step readiness/setup wizard;
|
||||
- system and deployment preflight engine;
|
||||
- structured rotating diagnostic JSONL logs;
|
||||
- aggressive credential/path redaction;
|
||||
- standard/strict support bundles with SHA-256 and fail-closed safety audit;
|
||||
- no automatic ingestion or persistence of raw runner logs;
|
||||
- root-owned declarative server target configuration;
|
||||
- cross-layer request-ID correlation;
|
||||
- canonical end-to-end setup guide;
|
||||
- 36 automated tests.
|
||||
|
||||
The source is now intended to be locally configured and testable without
|
||||
sharing credentials. It remains a developer preview until a real environment
|
||||
acceptance pass is completed.
|
||||
|
||||
## Milestone A — Real personal acceptance
|
||||
|
||||
- run the canonical setup guide on the target Windows machine;
|
||||
- connect the actual Gitea instance locally;
|
||||
- use one non-critical staging repository;
|
||||
- register a narrowly scoped trusted runner;
|
||||
- install the target configuration, entry point and status endpoint;
|
||||
- pass Deployment preflight;
|
||||
- validate commit -> push -> deploy -> status -> health -> rollback;
|
||||
- deliberately test stopped runner, wrong branch, missing workflow, failed
|
||||
health and lock contention;
|
||||
- export/inspect a strict diagnostic bundle from a failed test;
|
||||
- capture only non-secret environment-specific adjustments in documentation.
|
||||
|
||||
Exit: one real application can be released and restored without code changes to
|
||||
ForgeFlow itself.
|
||||
|
||||
## Milestone B — Git completeness
|
||||
|
||||
- partial-hunk staging/discard;
|
||||
- amend and signing checks;
|
||||
- richer branch publication/upstream controls;
|
||||
- conflict helper and editor integration;
|
||||
- protected-branch awareness;
|
||||
- pull-request creation;
|
||||
- submodule/worktree policy.
|
||||
|
||||
## Milestone C — Desktop operations
|
||||
|
||||
- native notifications and system tray;
|
||||
- background start preference;
|
||||
- notification center;
|
||||
- native menus and expanded keyboard navigation;
|
||||
- configurable editor/terminal commands;
|
||||
- repository attention rules and snoozing;
|
||||
- safer periodic remote fetch scheduling.
|
||||
|
||||
## Milestone D — Recovery and audit
|
||||
|
||||
- append-only audit export distinct from diagnostics;
|
||||
- deployment notes and release annotations;
|
||||
- explicit reconciliation of externally deployed versions;
|
||||
- per-environment recovery runbook links;
|
||||
- encrypted configuration backup/restore without token export;
|
||||
- deployment freeze and maintenance-window policies.
|
||||
|
||||
## Milestone E — Additional controlled adapters
|
||||
|
||||
- mutually authenticated ForgeFlow server agent;
|
||||
- Portainer stack deployment;
|
||||
- systemd adapter;
|
||||
- Kubernetes adapter.
|
||||
|
||||
Every adapter must retain exact version identity, allowlisting, lock control,
|
||||
health verification, diagnostic correlation and no arbitrary shell input.
|
||||
|
||||
## Milestone F — Productization
|
||||
|
||||
- Windows installer/portable acceptance;
|
||||
- macOS/Linux package validation;
|
||||
- code signing, notarization and signed updates;
|
||||
- dependency/secret/package scans;
|
||||
- accessibility review;
|
||||
- hundreds-of-repositories performance tests;
|
||||
- opt-in privacy-aware crash reporting;
|
||||
- documented Gitea/Git/runner support matrix;
|
||||
- stable configuration migration rollback policy.
|
||||
|
||||
- built-in private-Gitea source updater with backup and rollback;
|
||||
- Unraid server inventory, generated basic Compose and exact-SHA SSH deployment.
|
||||
@@ -0,0 +1,132 @@
|
||||
# Security model
|
||||
|
||||
ForgeFlow bridges developer credentials, local source trees and production
|
||||
release controls. The design favors constrained operations over arbitrary
|
||||
flexibility.
|
||||
|
||||
## Desktop boundary
|
||||
|
||||
- `nodeIntegration: false`;
|
||||
- `contextIsolation: true`;
|
||||
- renderer sandbox enabled;
|
||||
- Content Security Policy limited to packaged resources;
|
||||
- narrow frozen preload API;
|
||||
- IPC rejected unless it originates from the packaged file renderer;
|
||||
- external navigation restricted to HTTP(S);
|
||||
- renderer errors reported through sanitized diagnostic IPC;
|
||||
- support-bundle reveal restricted to the last archive created by the main
|
||||
process.
|
||||
|
||||
## Credentials and persistence
|
||||
|
||||
- Gitea token encrypted through Electron `safeStorage` where available;
|
||||
- session-only fallback when OS encryption is unavailable;
|
||||
- token omitted from renderer-visible public state;
|
||||
- encrypted token blob excluded from diagnostic bundles;
|
||||
- blank settings token field preserves the existing token;
|
||||
- atomic config replacement and restrictive permissions where supported;
|
||||
- service URLs reject embedded user credentials;
|
||||
- no token is required by setup/build scripts or documentation.
|
||||
|
||||
## Git operations
|
||||
|
||||
- Git executed through `execFile` argument arrays, never shell interpolation;
|
||||
- local repository and Git root verified;
|
||||
- file actions accept only repository-relative paths;
|
||||
- absolute paths, traversal and NUL characters rejected;
|
||||
- clone remotes restricted to supported Git protocols; embedded passwords
|
||||
rejected;
|
||||
- renderer supplies repository identity rather than a free-form remote URL;
|
||||
- automatic clone targets are calculated in the main process below a selected
|
||||
project root;
|
||||
- matching existing origins may be linked, while different repositories and
|
||||
non-empty ordinary folders are blocked;
|
||||
- branch names validated by Git;
|
||||
- fast-forward-only pull;
|
||||
- branch switching/creation require a clean tree;
|
||||
- selected-commit flow refuses hidden staged files outside the selection;
|
||||
- monitor pauses around mutating actions.
|
||||
|
||||
## Deployment
|
||||
|
||||
- fixed workflow filenames, branch and environment;
|
||||
- full 40–64 character SHA required;
|
||||
- local state re-read immediately before dispatch;
|
||||
- clean, published and synchronized branch required;
|
||||
- deployment SHA must equal local `HEAD`;
|
||||
- deploy and rollback SHA must belong to the allowed remote branch;
|
||||
- no free-form server commands over IPC or workflow inputs;
|
||||
- mandatory deployment preflight in the normal UI flow;
|
||||
- backend validation repeated after preflight;
|
||||
- exact target displayed in confirmation;
|
||||
- independent health and live-SHA checks;
|
||||
- rollback uses a separate fixed workflow and previous full SHA;
|
||||
- UUID request ID correlates desktop, workflow and server state.
|
||||
|
||||
## Diagnostics and redaction
|
||||
|
||||
- structured events are sanitized before writing;
|
||||
- IPC payloads and HTTP authorization headers are not logged;
|
||||
- sensitive object keys, including camelCase, are removed;
|
||||
- known active tokens, authorization strings, query tokens, URL passwords,
|
||||
private-key blocks and common token formats are redacted;
|
||||
- home/source paths are aliased;
|
||||
- strings and collections are bounded;
|
||||
- logs rotate by day/size and expire by retention policy;
|
||||
- support bundles offer deterministic strict-privacy aliases;
|
||||
- raw runner logs, diffs and source file contents are omitted from bundles;
|
||||
- bundle creation performs a final fail-closed scan for known secrets,
|
||||
private-key markers and URL credentials;
|
||||
- bundle SHA-256 is displayed for exact identification.
|
||||
|
||||
No generic detector can identify a completely unknown arbitrary secret printed
|
||||
without context by third-party code. ForgeFlow minimizes that residual risk by
|
||||
not exporting raw runner output and by requiring user inspection before sharing.
|
||||
|
||||
## Runner boundary
|
||||
|
||||
Use a production-capable runner only for repositories you trust. Give it a
|
||||
label unique to the intended environment and the narrowest repository or
|
||||
organization scope.
|
||||
|
||||
Avoid exposing a host Docker socket to untrusted jobs. Treat a runner capable of
|
||||
host deployment as privileged infrastructure.
|
||||
|
||||
## Server entry point
|
||||
|
||||
The runner account should not receive unrestricted sudo or SSH access. The
|
||||
included model uses:
|
||||
|
||||
- root-owned `/usr/local/bin/forgeflow-deploy`;
|
||||
- root-owned `/etc/forgeflow/targets.conf` without group/other write access;
|
||||
- a sudoers rule for that exact executable only;
|
||||
- exact repository/environment matching;
|
||||
- absolute-path and branch validation;
|
||||
- full-SHA remote ancestry proof;
|
||||
- per-target `flock` lock;
|
||||
- fixed Compose and healthcheck configuration;
|
||||
- atomic non-secret status JSON;
|
||||
- previous-SHA recording and non-zero failure exits.
|
||||
|
||||
## Remaining release hardening
|
||||
|
||||
- code-sign packages and signed updates;
|
||||
- validate private CA/TLS behavior in the target network;
|
||||
- dependency, secret and binary scans in CI;
|
||||
- package-level IPC/navigation regression tests;
|
||||
- OS-specific credential storage and installer acceptance;
|
||||
- rate/approval policies for team use;
|
||||
- threat-model every future deployment adapter separately.
|
||||
|
||||
|
||||
## SSH and updater additions
|
||||
|
||||
- SSH passwords and private-key passphrases use Electron `safeStorage`;
|
||||
- diagnostics receive those runtime secrets only for redaction and never export
|
||||
encrypted credential fields;
|
||||
- SSH deployment requires a pinned host-key fingerprint;
|
||||
- remote folders and Compose paths are validated against traversal;
|
||||
- tracked server-side changes block exact-SHA reset;
|
||||
- updater tokens are sent only to the configured Gitea origin;
|
||||
- update archives are checksummed and validated by the full local quality gate;
|
||||
- source backup is restored when an update fails.
|
||||
@@ -0,0 +1,485 @@
|
||||
# ForgeFlow setup and first-test guide
|
||||
|
||||
This is the canonical guide for turning the source release into a locally
|
||||
configured desktop application and testing one complete path:
|
||||
|
||||
```text
|
||||
local change -> commit -> push -> exact-SHA deployment -> healthcheck -> rollback
|
||||
```
|
||||
|
||||
You never need to provide your Gitea token, SSH key or server credentials to a
|
||||
developer. Enter them only on the computer or server where they belong.
|
||||
|
||||
---
|
||||
|
||||
## Part 1 — Prepare the Windows desktop
|
||||
|
||||
### 1. Extract the release
|
||||
|
||||
Extract the complete ForgeFlow ZIP to a normal local directory, for example:
|
||||
|
||||
```text
|
||||
C:\Tools\ForgeFlow
|
||||
```
|
||||
|
||||
Avoid running it directly from inside the ZIP or from a temporary email folder.
|
||||
|
||||
### 2. Install the prerequisites
|
||||
|
||||
Required:
|
||||
|
||||
- Node.js 22 or newer;
|
||||
- npm, normally installed with Node.js;
|
||||
- Git for Windows available on `PATH`;
|
||||
- a normal signed-in Windows desktop session so Electron can use OS credential
|
||||
encryption.
|
||||
|
||||
Optional manual check:
|
||||
|
||||
```powershell
|
||||
node --version
|
||||
npm --version
|
||||
git --version
|
||||
git config --global user.name
|
||||
git config --global user.email
|
||||
```
|
||||
|
||||
Configure the Git identity when either value is empty:
|
||||
|
||||
```powershell
|
||||
git config --global user.name "YOUR NAME"
|
||||
git config --global user.email "YOUR EMAIL"
|
||||
```
|
||||
|
||||
### 3. Run the local setup command
|
||||
|
||||
Open PowerShell in the extracted folder and run:
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process Bypass
|
||||
.\setup-windows.ps1
|
||||
```
|
||||
|
||||
This command:
|
||||
|
||||
1. checks Node.js, npm and Git;
|
||||
2. installs the declared project dependency versions;
|
||||
3. runs source validation and all automated tests;
|
||||
4. starts the Electron desktop application.
|
||||
|
||||
No Gitea or server credential is requested by the PowerShell script.
|
||||
|
||||
---
|
||||
|
||||
## Part 2 — Complete the ForgeFlow desktop wizard
|
||||
|
||||
The first launch uses five explicit steps.
|
||||
|
||||
### Step 1. Readiness
|
||||
|
||||
Select **Run readiness check**. ForgeFlow verifies:
|
||||
|
||||
- Git CLI availability;
|
||||
- Git author identity;
|
||||
- writable application storage;
|
||||
- writable diagnostic storage;
|
||||
- availability of operating-system credential encryption.
|
||||
|
||||
Warnings are informative. Red required checks block completion until resolved.
|
||||
A safe setup diagnostic ZIP can already be exported at this stage.
|
||||
|
||||
### Step 2. Gitea
|
||||
|
||||
Create a Gitea access token (personal access token) in your own Gitea account. The exact scope labels
|
||||
can vary by Gitea version. Give it only the minimum rights needed for:
|
||||
|
||||
- reading the repositories you want to show in ForgeFlow;
|
||||
- reading repository contents and branches;
|
||||
- reading Actions runs and jobs;
|
||||
- dispatching the fixed deployment and rollback workflows.
|
||||
|
||||
Do not put this token in a Markdown file, `.env`, workflow or chat message.
|
||||
|
||||
Enter locally in ForgeFlow:
|
||||
|
||||
```text
|
||||
Instance URL: https://YOUR-GITEA-HOST
|
||||
Access token: PASTE LOCALLY IN THE PASSWORD FIELD
|
||||
```
|
||||
|
||||
Select **Validate & continue**. ForgeFlow confirms the user identity and
|
||||
repository access. When OS encryption is available, the token is stored with
|
||||
Electron `safeStorage`; otherwise it remains session-only and must be entered
|
||||
again after restarting.
|
||||
|
||||
### Step 3. Folders
|
||||
|
||||
Choose one or more project roots that contain local repositories, for
|
||||
example:
|
||||
|
||||
```text
|
||||
C:\Development
|
||||
D:\Projects
|
||||
```
|
||||
|
||||
Do not select the entire system disk. A focused project root produces faster
|
||||
and clearer discovery.
|
||||
|
||||
The first configured root is also the default clone destination. When cloning
|
||||
`owner/repository`, ForgeFlow automatically creates:
|
||||
|
||||
```text
|
||||
<first-project-root>\repository
|
||||
```
|
||||
|
||||
The normal **Clone from Gitea** action does not open a folder picker. Use
|
||||
**Choose another location** only when a repository belongs under a different
|
||||
parent directory. ForgeFlow still creates the repository-named subfolder.
|
||||
|
||||
### Step 4. Discovery
|
||||
|
||||
ForgeFlow scans Git metadata and matches each local `origin` to a Gitea
|
||||
repository. Generated dependency directories are skipped.
|
||||
|
||||
### Step 5. Ready
|
||||
|
||||
Enter ForgeFlow. Repositories that could not be matched can still be linked or
|
||||
cloned from their repository screen. A clone is automatically linked and
|
||||
monitored after Git completes.
|
||||
|
||||
---
|
||||
|
||||
## Part 3 — Prepare one repository for deployment
|
||||
|
||||
Start with a non-critical staging application when possible.
|
||||
|
||||
### 1. Verify the local repository
|
||||
|
||||
The repository should have:
|
||||
|
||||
- a configured `origin` pointing to the same Gitea repository;
|
||||
- a normal branch such as `main`;
|
||||
- no unresolved conflicts;
|
||||
- an upstream branch after the first push.
|
||||
|
||||
### 2. Add the fixed Gitea Actions workflows
|
||||
|
||||
Copy:
|
||||
|
||||
```text
|
||||
examples/gitea-actions/deploy.yml
|
||||
examples/gitea-actions/rollback.yml
|
||||
```
|
||||
|
||||
to the target repository as:
|
||||
|
||||
```text
|
||||
.gitea/workflows/deploy.yml
|
||||
.gitea/workflows/rollback.yml
|
||||
```
|
||||
|
||||
Review the runner label in both files:
|
||||
|
||||
```yaml
|
||||
runs-on: forgeflow-production
|
||||
```
|
||||
|
||||
Replace it with the exact label of the trusted runner that can reach the target
|
||||
server environment. Commit and push these workflow files before running the
|
||||
deployment preflight.
|
||||
|
||||
The workflows accept only controlled inputs:
|
||||
|
||||
```text
|
||||
environment
|
||||
commit_sha or target_sha
|
||||
request_id
|
||||
```
|
||||
|
||||
ForgeFlow creates the `request_id` automatically so desktop diagnostics,
|
||||
Actions output and server status can be correlated without exposing a secret.
|
||||
|
||||
---
|
||||
|
||||
## Part 4 — Prepare the server and trusted runner
|
||||
|
||||
The example implementation targets a dedicated Git checkout deployed with
|
||||
Docker Compose. Adapt the allowlisted target values, not the security model.
|
||||
|
||||
### 1. Confirm the server prerequisites
|
||||
|
||||
On the target server, verify:
|
||||
|
||||
```bash
|
||||
git --version
|
||||
docker --version
|
||||
docker compose version
|
||||
curl --version
|
||||
flock --version
|
||||
```
|
||||
|
||||
The application checkout must already exist and have a working `origin` that the
|
||||
server can fetch without interactive prompts.
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
/srv/YOUR-APP
|
||||
/srv/YOUR-APP/compose.yml
|
||||
```
|
||||
|
||||
### 2. Install the target configuration
|
||||
|
||||
Copy the template:
|
||||
|
||||
```bash
|
||||
sudo install -d -o root -g root -m 0755 /etc/forgeflow
|
||||
sudo install -o root -g root -m 0640 \
|
||||
examples/server/forgeflow-targets.conf \
|
||||
/etc/forgeflow/targets.conf
|
||||
```
|
||||
|
||||
Edit it as root:
|
||||
|
||||
```bash
|
||||
sudo nano /etc/forgeflow/targets.conf
|
||||
```
|
||||
|
||||
Each active line has seven pipe-separated fields:
|
||||
|
||||
```text
|
||||
repository|environment|app_dir|branch|compose_file|healthcheck_url|status_file
|
||||
```
|
||||
|
||||
Example:
|
||||
|
||||
```text
|
||||
jens/my-app|staging|/srv/my-app-staging|main|/srv/my-app-staging/compose.yml|http://127.0.0.1:18080/health|/var/lib/forgeflow-status/my-app-staging.json
|
||||
```
|
||||
|
||||
Rules:
|
||||
|
||||
- repository must exactly match `owner/repository` in Gitea;
|
||||
- environment must exactly match the ForgeFlow profile value;
|
||||
- all filesystem paths must be absolute;
|
||||
- status files must stay under `/var/lib/forgeflow-status/`;
|
||||
- the configuration must remain root-owned and not group/other writable.
|
||||
|
||||
Validate permissions:
|
||||
|
||||
```bash
|
||||
sudo stat -c '%U %G %a %n' /etc/forgeflow/targets.conf
|
||||
```
|
||||
|
||||
Expected owner is `root`; a mode such as `640` is appropriate.
|
||||
|
||||
### 3. Install the allowlisted deployment entry point
|
||||
|
||||
```bash
|
||||
sudo install -o root -g root -m 0755 \
|
||||
examples/server/forgeflow-deploy \
|
||||
/usr/local/bin/forgeflow-deploy
|
||||
```
|
||||
|
||||
The script:
|
||||
|
||||
- accepts only a valid repository, environment, full SHA and request ID;
|
||||
- resolves the repository/environment through the root-owned target file;
|
||||
- rejects unsafe paths and branches;
|
||||
- prevents concurrent deployments with `flock`;
|
||||
- fetches the allowed branch;
|
||||
- proves that the requested SHA is an ancestor of the remote branch;
|
||||
- resets only the dedicated deployment checkout;
|
||||
- runs the fixed Docker Compose redeploy;
|
||||
- performs repeated healthchecks;
|
||||
- writes live, previous and requested SHAs atomically;
|
||||
- records the correlation request ID and last exit code.
|
||||
|
||||
### 4. Restrict runner elevation
|
||||
|
||||
Copy and edit the sudoers example:
|
||||
|
||||
```bash
|
||||
sudo install -o root -g root -m 0440 \
|
||||
examples/server/forgeflow-runner.sudoers \
|
||||
/etc/sudoers.d/forgeflow-runner
|
||||
sudo visudo -cf /etc/sudoers.d/forgeflow-runner
|
||||
```
|
||||
|
||||
Replace `act_runner` with the actual trusted runner account. Do not grant that
|
||||
account unrestricted passwordless `sudo`, shell access or wildcard commands.
|
||||
|
||||
### 5. Register and start the Gitea runner
|
||||
|
||||
Register a dedicated trusted runner according to your Gitea instance and runner
|
||||
version. Attach the exact label referenced by the workflow, for example:
|
||||
|
||||
```text
|
||||
forgeflow-production
|
||||
```
|
||||
|
||||
Only repositories you control should be able to schedule jobs on a runner with
|
||||
production access.
|
||||
|
||||
---
|
||||
|
||||
## Part 5 — Publish server version status
|
||||
|
||||
The server script writes one non-secret JSON status document per environment.
|
||||
Serve it over HTTPS independently of the application process so it can still
|
||||
report a failed release.
|
||||
|
||||
Copy and adapt:
|
||||
|
||||
```text
|
||||
examples/server/nginx-forgeflow-status.conf
|
||||
```
|
||||
|
||||
Example URL:
|
||||
|
||||
```text
|
||||
https://YOUR-APP-HOST/.well-known/forgeflow
|
||||
```
|
||||
|
||||
Expected response:
|
||||
|
||||
```json
|
||||
{
|
||||
"repository": "jens/my-app",
|
||||
"environment": "staging",
|
||||
"request_id": "00000000-0000-0000-0000-000000000000",
|
||||
"commit_sha": "0123456789abcdef0123456789abcdef01234567",
|
||||
"previous_sha": "89abcdef0123456789abcdef0123456789abcdef",
|
||||
"requested_sha": "0123456789abcdef0123456789abcdef01234567",
|
||||
"deployed_at": "2026-07-24T12:00:00Z",
|
||||
"health": "healthy",
|
||||
"last_exit_code": 0
|
||||
}
|
||||
```
|
||||
|
||||
Test from the ForgeFlow desktop computer:
|
||||
|
||||
```powershell
|
||||
Invoke-WebRequest "https://YOUR-APP-HOST/.well-known/forgeflow"
|
||||
Invoke-WebRequest "https://YOUR-APP-HOST/health"
|
||||
```
|
||||
|
||||
See [`STATUS_ENDPOINT.md`](STATUS_ENDPOINT.md) for the accepted contract.
|
||||
|
||||
---
|
||||
|
||||
## Part 6 — Create the deployment profile in ForgeFlow
|
||||
|
||||
Open the linked repository and add an environment.
|
||||
|
||||
Fill in:
|
||||
|
||||
```text
|
||||
Profile name: Staging
|
||||
Environment input: staging
|
||||
Allowed branch: main
|
||||
Deploy workflow: deploy.yml
|
||||
Rollback workflow: rollback.yml
|
||||
Status URL: https://YOUR-APP-HOST/.well-known/forgeflow
|
||||
Healthcheck URL: https://YOUR-APP-HOST/health
|
||||
Confirmation: enabled
|
||||
```
|
||||
|
||||
Save the profile.
|
||||
|
||||
---
|
||||
|
||||
## Part 7 — Run Deployment preflight
|
||||
|
||||
Select **Preflight** on the environment card. ForgeFlow must verify:
|
||||
|
||||
1. local repository link;
|
||||
2. valid Git working tree;
|
||||
3. allowed current branch;
|
||||
4. clean working tree;
|
||||
5. published upstream;
|
||||
6. zero commits ahead and zero behind;
|
||||
7. exact local SHA exists on the allowed remote branch;
|
||||
8. local deploy workflow exists;
|
||||
9. remote deploy workflow exists on Gitea;
|
||||
10. Gitea Actions API is readable;
|
||||
11. a configured server status endpoint;
|
||||
12. current status-endpoint reachability;
|
||||
13. application healthcheck result when configured.
|
||||
|
||||
The status URL is mandatory because ForgeFlow uses it after the workflow to prove
|
||||
that the server applied the exact SHA for the exact request ID. An unreachable
|
||||
status document can be a warning before the very first deployment because the
|
||||
server script may create it, but the operation cannot finish successfully until
|
||||
the endpoint returns the requested SHA and request ID. Required failures block
|
||||
the Continue button and the deployment backend repeats its own Git/SHA checks at
|
||||
dispatch time.
|
||||
|
||||
---
|
||||
|
||||
## Part 8 — First safe end-to-end test
|
||||
|
||||
Use a staging profile first.
|
||||
|
||||
1. Make a harmless visible change.
|
||||
2. Review the diff in ForgeFlow.
|
||||
3. Enter a commit message.
|
||||
4. Select **Commit & push**.
|
||||
5. Confirm that Local and Gitea show the same SHA.
|
||||
6. Select **Deploy SHA -> Staging**.
|
||||
7. Review and continue through Deployment preflight.
|
||||
8. Confirm the exact SHA.
|
||||
9. Follow workflow, job and healthcheck progress.
|
||||
10. Confirm that the server status endpoint reports the same full SHA.
|
||||
11. Create a second harmless commit and deploy it.
|
||||
12. Use **Rollback** to restore the recorded previous SHA.
|
||||
|
||||
Also test deliberately:
|
||||
|
||||
- an uncommitted local change;
|
||||
- a local commit that was not pushed;
|
||||
- the wrong branch;
|
||||
- a missing workflow file;
|
||||
- a stopped runner;
|
||||
- a failed healthcheck;
|
||||
- a second deployment while the lock is held.
|
||||
|
||||
ForgeFlow should block unsafe local states and clearly retain failed operation
|
||||
metadata for diagnostics.
|
||||
|
||||
---
|
||||
|
||||
## Part 9 — Export a diagnostic bundle without sharing credentials
|
||||
|
||||
Open **Diagnostics**.
|
||||
|
||||
1. Run **System preflight**.
|
||||
2. Select **Strict privacy** when sharing externally.
|
||||
3. Select **Create diagnostic ZIP**.
|
||||
4. Inspect the ZIP before sending it.
|
||||
|
||||
The bundle deliberately contains no encrypted token field and omits raw runner
|
||||
logs. Before writing the ZIP, ForgeFlow runs a safety audit for known runtime
|
||||
secrets, private-key markers and unredacted URL credentials. If that audit
|
||||
fails, no bundle is written.
|
||||
|
||||
See [`DIAGNOSTICS.md`](DIAGNOSTICS.md) for the exact contents and limitations.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Part 8 — Configure an Unraid server
|
||||
|
||||
Open **Settings → SSH / Unraid servers**. Enter the host, SSH port, username and
|
||||
`/mnt/user/appdata` as the base path. Prefer a private key. Save, then run
|
||||
**Test & trust** to record the server host-key fingerprint.
|
||||
|
||||
For an existing project, enter its current server folder name. ForgeFlow
|
||||
inspects the root Git repository, tracked modifications, Compose files and
|
||||
nested repositories before it permits deployment.
|
||||
|
||||
For a new project, use the repository name as server folder. Select the
|
||||
repository Compose file or enable basic generated Compose and enter host and
|
||||
container ports.
|
||||
|
||||
See `docs/SSH_UNRAID_DEPLOYMENT.md`.
|
||||
@@ -0,0 +1,112 @@
|
||||
# SSH / Unraid deployment
|
||||
|
||||
ForgeFlow 0.4 can deploy an exact Gitea commit directly to an Unraid server over SSH.
|
||||
|
||||
## Security model
|
||||
|
||||
- Enter credentials only in the local ForgeFlow desktop window.
|
||||
- Prefer an Ed25519 private key over a password.
|
||||
- ForgeFlow stores passwords and private-key passphrases through Electron safe storage.
|
||||
- The first successful test records the SSH host-key fingerprint.
|
||||
- Later connections fail closed when that fingerprint changes.
|
||||
- Diagnostics redact the Gitea token, SSH password and private-key passphrase.
|
||||
- ForgeFlow never sends arbitrary commands entered through the renderer. Deployment commands are assembled from validated profile fields.
|
||||
|
||||
## Configure the server
|
||||
|
||||
Open **Settings → SSH / Unraid servers → Add server**.
|
||||
|
||||
Typical Unraid values:
|
||||
|
||||
```text
|
||||
Name: Unraid
|
||||
Host: 192.168.1.10
|
||||
Port: 22
|
||||
Username: root
|
||||
Base path: /mnt/user/appdata
|
||||
Auth: Private key
|
||||
```
|
||||
|
||||
Save the server, then choose **Test & trust**. ForgeFlow verifies SSH, Git and Docker Compose and records the host-key fingerprint.
|
||||
|
||||
## Existing application folder
|
||||
|
||||
Create a deployment profile and choose **SSH / Unraid**.
|
||||
|
||||
For an existing folder:
|
||||
|
||||
```text
|
||||
Server folder: lumaops
|
||||
Remote path: /mnt/user/appdata/lumaops
|
||||
Compose file: docker-compose.yml
|
||||
```
|
||||
|
||||
ForgeFlow inspects the folder before deployment. An existing deployment is adopted only when the project root is a Git working tree. Tracked server-side changes block deployment. Untracked runtime paths such as `.env`, `appdata`, `data`, `logs`, `config` and `compose.override.yml` remain untouched by `git reset --hard`.
|
||||
|
||||
Keep the root `.git` directory. It is used to verify the exact commit, update the working tree and roll back to the previous SHA.
|
||||
|
||||
Nested Git repositories are reported as warnings and are never removed automatically.
|
||||
|
||||
When a Dockerfile is present, preflight also inspects `.dockerignore`. It reports
|
||||
whether `.git` is excluded and warns when existing preserved runtime folders or
|
||||
nested repositories would still be sent as Docker build context. Fix those
|
||||
rules in the repository and commit them rather than changing only the live
|
||||
server copy.
|
||||
|
||||
## New application folder
|
||||
|
||||
For a new project, ForgeFlow creates:
|
||||
|
||||
```text
|
||||
/mnt/user/appdata/<repository-name>
|
||||
```
|
||||
|
||||
The Unraid server clones the configured Git URL on the selected branch. The server therefore needs access to that repository, normally through an SSH deploy key or an existing trusted Gitea SSH identity.
|
||||
|
||||
Two Compose modes are available:
|
||||
|
||||
1. **Use repository Compose file** — recommended for real applications. Keep ports, volumes, devices, networks and Unraid labels version-controlled.
|
||||
2. **Generate basic ForgeFlow Compose** — suitable for a simple Dockerfile-based application. ForgeFlow asks for host port, container port, service/container name, Web UI URL and icon URL and writes `.forgeflow/compose.forgeflow.yml`.
|
||||
|
||||
Generated Compose deliberately stays minimal. Projects requiring USB devices, GPU access, custom networks, secrets or multiple services should provide their own Compose file.
|
||||
|
||||
## Deployment sequence
|
||||
|
||||
1. Verify that the local repository is clean, on the allowed branch and fully synchronized with Gitea.
|
||||
2. Verify that the exact requested SHA exists on `origin/<branch>`.
|
||||
3. Verify the repository Compose file or Dockerfile locally.
|
||||
4. Connect through pinned SSH.
|
||||
5. Inspect the target folder.
|
||||
6. Refuse tracked server-only modifications.
|
||||
7. Clone when the folder does not exist.
|
||||
8. Fetch the configured branch without allowing interactive credential prompts.
|
||||
9. Verify again on the server that the requested full SHA belongs to `origin/<branch>`.
|
||||
10. Save the current SHA as the rollback target.
|
||||
11. Reset the working tree to the exact requested SHA.
|
||||
12. Validate the selected Compose file.
|
||||
13. Run `docker compose up -d --build --remove-orphans`.
|
||||
14. Store non-secret state under `.forgeflow/` and run the configured healthcheck.
|
||||
|
||||
## Folder names
|
||||
|
||||
The default folder is the repository name. Existing deployments can keep another folder name by entering it explicitly in the profile. ForgeFlow does not rename populated application folders automatically because Docker paths, scripts and external integrations may depend on them.
|
||||
|
||||
A later controlled migration can align names after a successful backup and downtime window.
|
||||
|
||||
## Rollback
|
||||
|
||||
After a successful deployment, the previous SHA is stored in:
|
||||
|
||||
```text
|
||||
.forgeflow/previous-sha
|
||||
```
|
||||
|
||||
Rollback is accepted only for the exact SHA currently recorded as the previous
|
||||
deployment. ForgeFlow rechecks that SHA against the configured Gitea branch,
|
||||
refuses tracked server-side changes, resets the same working tree, runs Docker
|
||||
Compose again and repeats the healthcheck. The version that was live before the
|
||||
rollback becomes the new rollback target.
|
||||
|
||||
## Before the first real deployment
|
||||
|
||||
Back up the application folder and its persistent data. Run **Preflight** and resolve every failed check. Warnings, such as a nested Git repository, should be reviewed but do not automatically delete or modify anything.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Server status endpoint contract
|
||||
|
||||
A workflow can report success while the wrong application version is running.
|
||||
ForgeFlow therefore supports a small server-side endpoint that independently
|
||||
reports the deployed commit.
|
||||
|
||||
## Canonical response
|
||||
|
||||
```json
|
||||
{
|
||||
"repository": "jens/example-app",
|
||||
"environment": "production",
|
||||
"request_id": "3a6ed71c-d52d-4d8d-9678-96e0c9456a81",
|
||||
"commit_sha": "0123456789abcdef0123456789abcdef01234567",
|
||||
"previous_sha": "89abcdef0123456789abcdef0123456789abcdef",
|
||||
"requested_sha": "0123456789abcdef0123456789abcdef01234567",
|
||||
"deployed_at": "2026-07-24T13:00:00Z",
|
||||
"health": "healthy",
|
||||
"last_exit_code": 0
|
||||
}
|
||||
```
|
||||
|
||||
Required for exact version verification:
|
||||
|
||||
- `commit_sha`: full 40–64 character hexadecimal commit identity.
|
||||
|
||||
Recommended:
|
||||
|
||||
- `previous_sha`: previous successful commit used by rollback;
|
||||
- `requested_sha`: SHA requested by the latest deployment attempt;
|
||||
- `request_id`: ForgeFlow operation correlation identifier;
|
||||
- `deployed_at`: ISO-8601 timestamp;
|
||||
- `health`: `healthy`, `deploying` or `unhealthy`;
|
||||
- `last_exit_code`: server entry-point result, with `0` for success;
|
||||
- `repository` and `environment`: useful for human consistency checks.
|
||||
|
||||
ForgeFlow also accepts `commitSha`, `sha`, `previousSha`, `requestId` and nested
|
||||
`version.sha`, but canonical snake-case fields are preferred.
|
||||
|
||||
## Isolation
|
||||
|
||||
Serve the endpoint independently from the deployed application when practical.
|
||||
A static JSON file exposed by the reverse proxy remains readable when the
|
||||
application fails to boot. The included deployment script writes it atomically.
|
||||
|
||||
The JSON file is non-secret and can be served read-only. Do not include tokens,
|
||||
host credentials, environment variables, registry secrets or stack traces.
|
||||
|
||||
## Profile configuration
|
||||
|
||||
Set both URLs when available:
|
||||
|
||||
- **Status URL**: returns this document and exact live SHA;
|
||||
- **Healthcheck URL**: returns a successful HTTP status only when the application
|
||||
is operational.
|
||||
|
||||
After an Actions run succeeds, ForgeFlow checks both. It marks the operation
|
||||
failed when the healthcheck is unhealthy or the server reports another SHA than
|
||||
the requested deployment.
|
||||
@@ -0,0 +1,99 @@
|
||||
# Stitch review and design corrections
|
||||
|
||||
## What worked well
|
||||
|
||||
The Stitch export established a strong visual starting point:
|
||||
|
||||
- A restrained graphite theme suitable for long sessions.
|
||||
- Compact desktop density.
|
||||
- Clear technical typography.
|
||||
- Useful deployment progress and failure concepts.
|
||||
- A credible developer-tool tone without excessive decoration.
|
||||
- Good use of green, amber and red for operational state.
|
||||
|
||||
## What was changed
|
||||
|
||||
### 1. From IDE shell to release cockpit
|
||||
|
||||
The export contained navigation for Editor, Monitoring and Extensions. Those features would blur the product into an incomplete IDE. ForgeFlow instead complements the user's existing editor and terminal.
|
||||
|
||||
The product boundary is now:
|
||||
|
||||
```text
|
||||
Understand repository state -> perform safe Git action -> release exact version
|
||||
```
|
||||
|
||||
### 2. One navigation model
|
||||
|
||||
The mock-ups mixed a top product navigation with a broad left application navigation. The implementation uses:
|
||||
|
||||
- A compact top bar for global search, identity, refresh and theme.
|
||||
- A left rail for Overview, Deployments, Settings and repositories.
|
||||
- Repository tabs only inside the selected project.
|
||||
|
||||
### 3. Operational cards instead of generic statistics
|
||||
|
||||
CPU, queue or server graphs are not useful unless ForgeFlow becomes a monitoring suite. The overview now answers:
|
||||
|
||||
- Which projects have local changes?
|
||||
- Which commits are not pushed?
|
||||
- Which repositories are behind or conflicted?
|
||||
- Which exact commits are ready to deploy?
|
||||
|
||||
### 4. Persistent Local -> Gitea -> Server rail
|
||||
|
||||
The most important state was made visible at the top of every repository workspace. The user no longer needs to infer synchronization from several unrelated badges.
|
||||
|
||||
### 5. Contextual action panel
|
||||
|
||||
The right panel now changes with state:
|
||||
|
||||
- Link or clone.
|
||||
- Resolve conflict.
|
||||
- Commit and push.
|
||||
- Fast-forward synchronize.
|
||||
- Push commits.
|
||||
- Configure deployment.
|
||||
- Deploy exact SHA.
|
||||
- Explain the blocking error.
|
||||
|
||||
Only one action is visually dominant.
|
||||
|
||||
### 6. Diff viewer, not editor
|
||||
|
||||
ForgeFlow displays changed files and diffs, but deliberately opens the real project folder for editing. This avoids duplicating editor features and keeps the application technically realistic.
|
||||
|
||||
### 7. Safer deployment language
|
||||
|
||||
A generic **Deploy** button can hide too much. ForgeFlow displays the exact action:
|
||||
|
||||
```text
|
||||
Deploy b82f91a -> Production
|
||||
```
|
||||
|
||||
The confirmation state shows the repository, branch, full SHA and workflow file.
|
||||
|
||||
### 8. Desktop behavior
|
||||
|
||||
The implementation adds details that static screens could not provide:
|
||||
|
||||
- Native directory selection.
|
||||
- External-link restrictions.
|
||||
- Keyboard shortcut for global search.
|
||||
- Ctrl/Cmd+Enter for commit and push.
|
||||
- Resizable desktop layout.
|
||||
- Offline and error handling foundations.
|
||||
- Secure process boundary between UI and system operations.
|
||||
|
||||
## Visual direction retained
|
||||
|
||||
The implementation intentionally keeps:
|
||||
|
||||
- Deep neutral background and panels.
|
||||
- Blue primary actions.
|
||||
- Green synchronization and health.
|
||||
- Amber pending work.
|
||||
- Red actual failures and conflicts.
|
||||
- Compact status badges.
|
||||
- Monospace only for branches, commits, paths and logs.
|
||||
- Minimal decorative effects.
|
||||
@@ -0,0 +1,106 @@
|
||||
# Test matrix
|
||||
|
||||
## Automated in v0.4.0
|
||||
|
||||
The suite contains 59 passing tests.
|
||||
|
||||
### Git and repository behavior
|
||||
|
||||
- porcelain v2 ordinary and rename parsing;
|
||||
- HTTPS and SCP-style remote matching;
|
||||
- real temporary bare remote: status, diff, selected commit and push;
|
||||
- real temporary bare remote: commit-only, branch creation/publication and
|
||||
remote-SHA ancestry verification;
|
||||
- real stash creation, listing, pop and untracked-file restoration;
|
||||
- repository monitor baseline, change detection and pause/resume;
|
||||
- safe repository folder-name derivation from HTTPS and SSH clone URLs;
|
||||
- automatic target construction beneath the project root;
|
||||
- missing, empty and matching-checkout clone target handling;
|
||||
- different repository, ordinary non-empty folder and file conflict rejection.
|
||||
|
||||
### Gitea and deployment behavior
|
||||
|
||||
- Gitea URL/credential validation;
|
||||
- Actions run normalization across payload shapes;
|
||||
- optional query-filter compatibility retry;
|
||||
- runs-to-tasks fallback;
|
||||
- newest matching run selection;
|
||||
- repository workflow contents lookup and 404 behavior;
|
||||
- deployment terminal-status mapping;
|
||||
- controlled dispatch inputs that cannot be overridden by profile data;
|
||||
- exact post-workflow SHA and request-ID verification;
|
||||
- rollback input allowlisting and exact current previous-SHA enforcement;
|
||||
- complete deployment preflight with Git, workflow, Actions, status and health
|
||||
mocks.
|
||||
|
||||
### Security and diagnostics
|
||||
|
||||
- repository path traversal and absolute-path rejection;
|
||||
- workflow filename, branch, environment and full-SHA validation;
|
||||
- clone protocol and embedded-password rejection;
|
||||
- runtime token, authorization, query token, URL credential and private-key
|
||||
redaction;
|
||||
- camelCase and nested sensitive-key removal;
|
||||
- home-path aliasing;
|
||||
- deterministic strict-privacy identifier hashing;
|
||||
- required versus optional preflight blocking behavior;
|
||||
- system preflight before credentials are entered;
|
||||
- structured JSONL diagnostic writes;
|
||||
- support-bundle strict privacy and secret exclusion;
|
||||
- ZIP structure, deflate payloads and CRC validation.
|
||||
- Windows npm command-shim discovery through `npm_execpath` and `cmd.exe`;
|
||||
- normal direct npm discovery on non-Windows systems.
|
||||
|
||||
## Static source quality gate
|
||||
|
||||
`npm run verify` checks:
|
||||
|
||||
- all required source, documentation and server-template files;
|
||||
- JavaScript syntax across the project;
|
||||
- package version and required scripts;
|
||||
- desktop packaging metadata and icons;
|
||||
- Bash syntax for the server entry point;
|
||||
- status JSON parsing;
|
||||
- required setup-guide sections;
|
||||
- renderer entry hooks.
|
||||
|
||||
## Manual before a real production release
|
||||
|
||||
- setup wizard against the installed Gitea version;
|
||||
- repository discovery on the target Windows system;
|
||||
- token persistence through Windows credential protection;
|
||||
- HTTPS and/or SSH Git authentication;
|
||||
- actual Actions dispatch, run resolution and job visibility;
|
||||
- runner label and repository trust scope;
|
||||
- server target-file ownership/mode enforcement;
|
||||
- status endpoint through the real reverse proxy;
|
||||
- deployment lock, failed healthcheck and rollback;
|
||||
- diagnostic ZIP inspection after a deliberately failed deployment;
|
||||
- unsigned installer and portable build on Windows;
|
||||
- keyboard-only and screen-reader smoke test.
|
||||
|
||||
## Renderer smoke target
|
||||
|
||||
The standalone demo should be checked at minimum at:
|
||||
|
||||
- 1120 × 720;
|
||||
- 1440 × 900;
|
||||
- 1920 × 1080.
|
||||
|
||||
Required views now include setup readiness, dashboard, repository workspace,
|
||||
deployment preflight, active run, success/failure and Diagnostics.
|
||||
|
||||
|
||||
### v0.4 additions
|
||||
|
||||
- bounded independently scrollable changed-file layout;
|
||||
- explicit commit-message and selection readiness contract;
|
||||
- ITWorx.tech asset integration;
|
||||
- semantic update-version comparison;
|
||||
- exact-SHA Gitea update manifest lookup;
|
||||
- update repository path-injection rejection;
|
||||
- SSH host-key fingerprint helper;
|
||||
- remote shell quoting;
|
||||
- Unraid folder and Compose path escape rejection;
|
||||
- server inspection payload decoding;
|
||||
- SSH deployment preflight summary behavior.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Updating ForgeFlow on Windows
|
||||
|
||||
ForgeFlow stores its local token, server credentials, repository mappings,
|
||||
preferences, deployment profiles, diagnostics and operation history outside the
|
||||
source directory.
|
||||
|
||||
## Manual update to v0.4.0
|
||||
|
||||
1. Close ForgeFlow.
|
||||
2. Extract the v0.4.0 update package.
|
||||
3. Copy the contents of its `ForgeFlow` folder over the existing source folder.
|
||||
4. Do not create `ForgeFlow\ForgeFlow`.
|
||||
5. Open PowerShell in the existing folder.
|
||||
6. Run:
|
||||
|
||||
```powershell
|
||||
Set-ExecutionPolicy -Scope Process Bypass
|
||||
.\update-windows.ps1
|
||||
```
|
||||
|
||||
The script installs the new `ssh2` dependency, runs the environment doctor,
|
||||
verifies the source and executes all tests before starting ForgeFlow.
|
||||
|
||||
## Built-in updates after v0.4.0
|
||||
|
||||
Open **Settings → ForgeFlow updates**.
|
||||
|
||||
The default source is:
|
||||
|
||||
```text
|
||||
Gitea instance: the instance already configured in ForgeFlow
|
||||
Repository: Jens/ForgeFlow
|
||||
Branch: main
|
||||
```
|
||||
|
||||
The repository must contain a newer semantic version in `package.json`.
|
||||
|
||||
Choose:
|
||||
|
||||
1. **Check now**
|
||||
2. **Download update**
|
||||
3. **Apply & restart**
|
||||
|
||||
The source updater downloads the exact branch commit, records a SHA-256 checksum,
|
||||
backs up the installed source, applies the archive, runs `npm install` and
|
||||
`npm run check`, and restarts ForgeFlow. When validation fails it restores the
|
||||
previous source and starts that version again.
|
||||
|
||||
The update log is written beneath ForgeFlow's local user-data `updates` folder
|
||||
and does not contain the Gitea token.
|
||||
|
||||
The updater deliberately checks the semantic version stored in the remote
|
||||
`package.json`. Merely pushing a new commit without increasing that version does
|
||||
not present an update. Publish the complete validated ForgeFlow source to the
|
||||
configured repository and bump the version for every release.
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 137 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 105 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 116 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 132 KiB |
Reference in New Issue
Block a user