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
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ Run `mise run check` and `mise run generate:check` for every change. Release
changes also require the focused release/workflow tests and a current-host
compiled archive smoke through `mise run release:smoke`.

The hand-written Agent OS provider-ingress command and its security suites are
specified in `docs/architecture.md`, `test/secure-token-file.test.ts`, and
`test/agent-os-loader.test.ts`.
The hand-written HCloud setup flow and its security suites are specified in
`docs/architecture.md`, `test/secure-token-file.test.ts`, and
`test/hcloud-setup.test.ts`.

## Maintaining this file

Expand Down
83 changes: 28 additions & 55 deletions docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,63 +16,36 @@ Status: greenfield scaffold with local auth/config MVP.
spec fetch task performs only a read-only OpenAPI GET and rejects non-HTTPS
source URLs.

## Agent OS HCloud Provider Loader Companion

The one exception to the generated-public-command boundary is the compiled,
non-generated command:

```sh
akua agent-os load-hcloud-provider \
--workspace <exact-name-or-ws_id> \
--token-file <absolute-path> \
[--expected-ssh-key-fingerprint <provider-returned-fingerprint> \
[--expected-ssh-key-name <name>]]
```

It is a deliberately thin local companion to the server-owned cnap Agent OS
provider-loader transaction (`POST /v1/agent_os/hcloud_provider_loads`). The
cnap transaction is the canonical source of truth for workspace authorization,
provider identity and inventory validation, storage, idempotency, compensation,
revocation, and all provider policy. This CLI never implements an inventory,
uses generic `/secrets` or `/compute_configs` calls, opens a browser, runs a
shell child, or falls back to another endpoint.

The command requires workspace and token-file flags and rejects positional
input, `--token`, stdin, provider-token environment/profile input, API URL
overrides, debug body output, and retry transports. A provider-returned SSH key
fingerprint is optional and may be sent only when predeclared; its optional name
requires the fingerprint. With no expected key, cnap requires a fully empty
inventory. The CLI never derives identity from the provider token. It reads
normal Akua caller authentication only from the protected local Akua config;
`AKUA_API_TOKEN` is rejected for this command.
It sends that authentication in `Authorization`, the explicit selection in
`Akua-Context`, a newly generated `Idempotency-Key`, and a body containing the
provider token plus optional `expected_ssh_key_fingerprint` and
`expected_ssh_key_name`. The production base URL and route are fixed; tests may
inject a fake HTTPS transport only through an internal dependency seam. The
client allowlists only `loader_id`, `attestation_id`, `secret_id`,
`secret_version_id`, `compute_config_id`, and `expected_ssh_key_fingerprint`,
preserving the secret-version continuity field before spend.

The provider file is opened exactly once in the compiled process by a dedicated
Unix reader. The reader accepts only an absolute, caller-owned, regular `0600`
## Generic HCloud Setup

`akua hcloud setup --workspace <ws_id> --token-file <absolute-path>` is the
compiled local setup flow for an HCloud bring-your-own credential. It reads
caller auth from protected local Akua configuration and rejects environment
authentication. The provider token is accepted only from the hardened absolute
file descriptor reader; it never enters command arguments, stdin, environment,
children, logs, errors, configuration, cache, or rendered output.

Before cnap persistence, the command makes one bounded attempt for each HCloud
validation request: account authentication, complete paginated user inventory,
server quota, and the live `fsn1` / `CPX32` catalog and price checks. Incomplete,
unexpected, or ambiguous responses fail closed. The preflight never provisions
or spends.

After a successful preflight, the command uses only public generic cnap
`/v1/secrets` and `/v1/compute_configs` resources. Stable workspace-derived
idempotency keys create `cloud_provider/hcloud` only when an exact reusable
secret is absent, then retain its exact enabled version 1 ID. The compute config
uses `credential_scope.byom` with both that secret ID and version ID. Existing
resources are never changed. On a definite downstream rejection, compensation
deletes only a resource created and confirmed by this invocation; uncertain
outcomes are neither retried nor compensated.

The descriptor reader accepts only an absolute, caller-owned, regular `0600`
file. It obtains pre-open `lstat` metadata, opens with `O_NOFOLLOW | O_CLOEXEC`,
compares device/inode/UID/mode with `fstat`, performs one bounded descriptor
read, and closes before HTTP submission. It rejects symlinks, substitutions,
directories, devices, FIFOs, sockets, wrong owners, empty input, and oversized
input. The token is held only in a mutable byte buffer for request assembly;
the buffer is overwritten immediately after the single request attempt. Bun
cannot promise physical heap zeroisation, so the security contract is no
deliberate secret persistence or exposure through CLI interfaces, logs, reports,
or configuration. A stronger heap guarantee requires a reviewed native module,
not a weaker file or API contract.

The endpoint is a release dependency delivered by
[cnap #545](https://github.com/akua-dev/cnap/pull/545), implementing
`agentOs.hcloudProviderLoads.create`: its production delivery must complete and
its released route contract must exactly match this companion before CLI
publication or Phase A invocation. The companion's eventual CLI-owned release is coordinated as
`0.9.0`; it does not duplicate the multi-platform distribution scope in PR #21.
read, and closes before HTTP submission. The mutable source buffer is cleared
after the flow. Bun cannot promise physical heap zeroisation; the contract is no
deliberate secret persistence or exposure through CLI interfaces.

## Current Repo Boundary

Expand Down

This file was deleted.

49 changes: 49 additions & 0 deletions docs/superpowers/plans/2026-07-14-generic-hcloud-setup.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Generic HCloud Setup Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.

**Goal:** Replace the removed provider-loader with a secret-safe generic HCloud setup command.

**Architecture:** A command owns protected local inputs and delegates to an in-process HCloud preflight plus a generic cnap resource client. Both transports are injected in tests; production uses fixed HTTPS URLs and never retries an uncertain request.

**Tech Stack:** Bun, TypeScript, Bun test, cnap public OpenAPI endpoints.

## Global Constraints

- The only hand-written public command is `akua hcloud setup --workspace <ws_id> --token-file <absolute-path>`.
- Provider bytes are read only by `readSecureTokenFile`, never logged or passed to children, and cleared after use.
- Persistence uses only `/v1/secrets` and `/v1/compute_configs`, each with deterministic idempotency keys.
- Preflight never creates provider resources; uncertain outcomes are not retried or compensated.

---

### Task 1: Replace product-specific routing and documentation

**Files:**
- Delete: the released product-specific command, transport, and test files
- Modify: `src/bin/akua.ts`, `test/cli.test.ts`, `docs/architecture.md`

- [ ] Write a failing help/routing test for `akua hcloud setup` and absence of the removed command.
- [ ] Run `bun test test/cli.test.ts` and confirm the new assertion fails.
- [ ] Route the new command and replace documentation with its generic contract.
- [ ] Run `bun test test/cli.test.ts` and confirm it passes.

### Task 2: Add HCloud preflight and generic cnap setup tests

**Files:**
- Create: `test/hcloud-setup.test.ts`
- Create: `src/commands/hcloud.ts`, `src/runtime/hcloud-setup.ts`

- [ ] Write synthetic transport tests for pagination, invalid auth, inventory, quota/catalog/price rejection, no uncertain retry, version continuity, reuse, success, and ownership-safe compensation.
- [ ] Run `bun test test/hcloud-setup.test.ts` and confirm it fails because the command is absent.
- [ ] Implement the smallest injected transport interfaces and fixed-route production clients that satisfy the tests.
- [ ] Run `bun test test/hcloud-setup.test.ts` and confirm it passes.

### Task 3: Verify generated and release surfaces

**Files:**
- Modify: `docs/architecture.md`, `AGENTS.md` only if durable repository guidance changes

- [ ] Confirm no product-specific route or naming remains in source, tests, or docs.
- [ ] Run `mise run check`, `mise run generate:check`, focused release/workflow tests, and `mise run release:smoke`.
- [ ] Commit the implementation, integrate current `origin/main`, and re-run the same verification.
Loading
Loading