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.
|
||||
Reference in New Issue
Block a user