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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,5 @@ jobs:
- run: npm ci
- run: npx prisma generate
- run: bash -n scripts/install
- run: cd scripts && sha256sum -c install.sha256
- run: npm run build
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ jobs:
- run: npm ci
- run: npx prisma generate
- run: bash -n scripts/install
- run: cd scripts && sha256sum -c install.sha256
- run: npm run test
- run: npm run build
11 changes: 11 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,14 @@ This version has breaking changes — APIs, conventions, and file structure may
- Post-install verification covers container health, persistent DB volume, host execution, PTY relay, MCP discovery, OAuth metadata, consumed claim state, and public HTTPS when configured.
- Cloudflare/tunnel credentials are secrets and must be encrypted at rest. Never return them to the browser after save.
- Additional VPS targets are explicit later connections. Do not conflate “where GroundControl runs” with “all servers GroundControl may manage.”


### Upgrade safety

- `scripts/install --preview` must remain non-mutating with respect to the running GroundControl instance.
- `--upgrade` must identify persistent `/app/prisma` storage before any migration-capable image is started.
- Upgrade targets should run by resolved registry digest when available; do not regress the canonical installer to mutable-tag-only Compose state.
- Back up SQLite plus Compose/env state while the old container is quiesced.
- If the new container fails startup/health, restore the DB and previous image/config automatically and verify rollback health.
- A successful rollback after a failed upgrade still exits non-zero and reports `upgrade_rolled_back`.
- `--uninstall` preserves data by default. Destructive purge must never be implicit.
19 changes: 19 additions & 0 deletions docs/agent-assisted-distribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,22 @@ The result is persisted and returned as structured data instead of shell-log sou
- publishing requires authenticated admin access;
- external agents receive MCP/OAuth grants, not operator sessions;
- provider/tunnel credentials remain encrypted at rest.


## Upgrade and recovery contract

The canonical installer also owns upgrades. Agents should call `--preview` before `--upgrade`.

A guarded upgrade:

1. identifies the current image and persistent `/app/prisma` storage;
2. pulls and resolves the requested image to a digest;
3. quiesces the app and backs up SQLite plus Compose/env state;
4. starts the new digest-pinned image;
5. treats the container health check as the migration/startup acceptance gate;
6. restores the previous DB, image and configuration if the gate fails;
7. returns structured evidence.

An automatic rollback that restores health exits non-zero because the requested upgrade still failed. Agents should report the rollback as successful recovery, not as a successful upgrade.

`--uninstall` is data-preserving by default. It removes the runtime but leaves the database volume and install directory available for recovery.
65 changes: 61 additions & 4 deletions docs/agent-assisted-installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,17 @@ curl -fsSL https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/mai
| sudo bash -s -- --json
```

For a download/verify/run flow:

```bash
curl -fsSLO https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/install
curl -fsSLO https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/install.sha256
sha256sum -c install.sha256
sudo bash install --json
```

CI verifies `scripts/install.sha256` on every change to keep the published checksum in sync.

Progress is written to stderr in JSON mode. stdout contains one final JSON object.

## Fresh-install result
Expand Down Expand Up @@ -82,11 +93,57 @@ Running the canonical installer against a healthy existing instance does not upd

- already claimed → `already_claimed`, no change;
- healthy but unclaimed → rotate/return a fresh claim, no image change;
- explicit `--upgrade` → refresh the requested image/version.
- explicit `--upgrade` → run the guarded upgrade transaction.

## Upgrade preview

Before changing a running instance:

```bash
curl -fsSL https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/install \
| sudo bash -s -- --preview --version <tag-or-short-sha> --json
```

Preview checks the current container, persistent DB mount, target image reachability and available disk without changing the running instance.

## Guarded upgrade

```bash
curl -fsSL https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/install \
| sudo bash -s -- --upgrade --version <tag-or-short-sha> --json
```

GroundControl:

1. pulls the requested image while the current instance is still running;
2. resolves the pulled tag to a registry digest when available;
3. stops the current container briefly for a consistent SQLite volume backup;
4. saves the previous Compose/env state;
5. starts the digest-pinned image;
6. waits for the health check after migrations;
7. restores the DB + previous image/config automatically when the new instance fails health;
8. records `result.json` and failed-upgrade logs in the backup directory.

Machine-readable outcomes include:

- `upgrade_complete`
- `upgrade_rolled_back`
- `rollback_failed`

The last three backup directories are retained by default.

## Data-preserving uninstall

```bash
curl -fsSL https://raw.githubusercontent.com/teckedd-code2save/groundcontrol/main/scripts/install \
| sudo bash -s -- --uninstall --json
```

This removes the runtime container/bridge processes but preserves the GroundControl DB volume and install directory for recovery.

## Versioning

`--version TAG` pins the container tag/short SHA. Production distribution should prefer published release tags or immutable SHA tags over `latest`.
`--version TAG` selects a release/short-SHA tag. The installer resolves that tag to the pulled registry digest when possible and writes the immutable digest into the generated Compose file.

## Security properties

Expand All @@ -97,6 +154,6 @@ Running the canonical installer against a healthy existing instance does not upd
- claim token is random, short-lived, hashed at rest, single-use;
- no bootstrap credential survives successful claim.

## Next distribution slice
## Post-claim distribution

The remaining #93 work is post-claim automation: supported HTTPS/Caddy or outbound bridge setup, structured host-execution/PTY/MCP/OAuth verification, release-channel upgrades and rollback evidence.
After claim, onboarding can keep the instance private or publish it through direct Caddy HTTPS, a named Cloudflare Tunnel, or a temporary outbound HTTPS bridge. GroundControl then verifies host execution, PTY, MCP discovery, OAuth metadata, persistent storage, consumed claim state and public HTTPS when configured.
Loading
Loading