Skip to main content
Live with caveats. This area is real and usable, but the docs intentionally call out operational or UX limits that still matter.

Goal

Save explicit source, placement and database choices, create configuration through native governed actions, and review a separate coordinated release.

Prerequisites

  • An account with Application recipes enabled. The repository-creation and partial-progress workflow described below is implemented for the next release.
  • An accessible GitHub repository and branch. A maintained sample download must be copied into your own repository before selecting it.
  • Stackshift hosting capacity or one healthy owner-controlled connected node (BYOS), plus an active PostgreSQL size or compatible existing database.
  • Infrastructure funding and AI funding are separate. A new hosted database shows its available catalog rate and billing assumptions. The complete total remains unavailable. Workloads on your own server, including a VPS provisioned through StackShift, add no workload hosting charge; server provisioning or rental remains separate. Reused databases do not inherit a new hosted allocation rate.

Workflow

1
Open Templates → Application recipes. Select App + PostgreSQL, App + PostgreSQL + Assets + Mail, API + worker or Background automation, then choose the maintained sample or your own GitHub repository.
2
Choose the repository, branch, exact workload root and install/build/start/release commands. Empty optional commands are explicit decisions. The sample migration runs only in the app/API coordinated release hook, never in the private worker.
3
Select a new or existing Application and its hosting or BYOS placement. For BYOS, choose an explicit healthy node. Select a new PostgreSQL database or a compatible database to reuse.
4
Select additional variables by reference metadata. Values never enter recipe responses. DATABASE_URL is supplied by a private_runtime writer binding.
5
Save the setup, review the remaining actions and continue one step at a time. Native resource IDs, approvals and controller references survive reloads.
6
After configuration and database readiness, review the separate release. Follow its retained operation to completion; configuration saved is not deployment success.
7
Verify the deployed health endpoint, write a unique record through the app and read it back. Local controlled readiness observations do not qualify a deployed endpoint.

Resume setup and create a sample repository (next release)

Save progress preserves incomplete source, placement, database and workload choices in an owner-only onboarding setup. Its URL reopens the editor. Unsaved edits also survive refresh in the same browser tab, scoped to the signed-in account and recipe version; use Save progress before switching devices. Variable references are saved, never secret values. For a maintained sample, choose Set up sample repository, then enter your GitHub username or organization, repository name and visibility (private by default). Create repository uses the existing GitHub connection to copy the exact versioned sample and returns its repository and default branch to the saved configuration. It does not create or deploy infrastructure. Organization policies and your existing repository-creation permissions still apply. If GitHub needs reconnecting, open connection settings from the saved setup, then use Return to saved recipe setup. Check connection refreshes access. Interrupted repository requests retain the destination, repository identity and sample digest. Resume reconciles that same destination; existing repositories and concurrent branch changes are not overwritten. An active attempt holds a two-minute claim. Check repository status reads the latest receipt. When GitHub accepted a creation request but its outcome remains unknown and the repository cannot be found, StackShift does not blindly repeat it. Inspect GitHub before starting another draft or select an existing repository. Repositories created by this flow remain yours; cancelling a setup does not delete them. Complete the configuration and choose Save setup for review before using the existing configuration and release approvals. Owner-session APIs: POST /api/v1/recipe-drafts with Idempotency-Key and an explicit recipe version; POST /api/v1/recipe-setups/{id}/save-draft with expected_revision and configuration; GET /api/v1/recipe-repository-account; POST /api/v1/recipe-setups/{id}/repository with expected_revision, owner, name and private. These onboarding mutations are unavailable to delegated connections. No new migration or OAuth scope is introduced. Existing sample downloads and repository selection remain supported. This addition is implemented locally, not yet confirmed deployed.

Infrastructure quote contract (next release)

Deployments and databases on an owner-managed server have zero incremental StackShift workload hosting charges, including deployments onto a VPS provisioned through StackShift. Available server capacity is the deployment limit. The usage worker excludes connected-node and verified owner-node workloads from hosted compute/database usage and project overage billing. Server purchase/rental and separately purchased services keep their own billing. This correction does not alter or refund historical usage records. Hosted PostgreSQL component rates explicitly use NGN kobo per hour: amount 100 means ₦1 per hour. This preserves the existing database price display and NGN usage settlement; it does not convert rates or change billing amounts. The component is quoted before plan allowances. Workload compute, storage growth, backups, network, taxes and external BYOS provider costs remain excluded, so the complete infrastructure total is unavailable. The review retains the priced database component’s price_revision plus quoted_at and expires_at. Quotes are valid for 15 minutes. Catalog changes invalidate the reviewed dependency, and expired quotes require planning again before a new recipe step is admitted or handed to its existing controller. Controller approval remains a separate decision. Replaying an already retained step request returns its original result; expiry never creates a replacement effect. This recipe quote is not an account-wide spending cap or a promise to lock billing rates for a resource’s lifetime.

One versioned recipe definition

GET /api/v1/application-recipes and GET /api/v1/application-recipes/{recipeID} expose the canonical catalog. GET /api/v1/application-recipes/{recipeID}/sample?version=1 downloads a deterministic archive; compare X-Content-SHA256 with sample_sha256 in the definition. Saved recipe_version must be a positive, concrete catalog version. Pass the same version to definition and sample endpoints; unsupported versions are rejected. API + worker version 1 includes a public API, a private worker with a health listener, and PostgreSQL-backed jobs. Run npm ci, npm run build and npm run migrate once; then npm run start:api and npm run start:worker in separate processes. npm test submits a unique job and polls its persisted result. The worker uses bounded leased claims, limited retries and graceful shutdown. App + PostgreSQL version 1 includes a Node.js/TypeScript app, bounded PostgreSQL pool, idempotent migration, graceful shutdown, health endpoint and a write/read smoke test. Use npm ci, npm run build, npm run migrate and npm start locally. npm test uses SAMPLE_URL and creates a unique record without resetting the database.

Background automation and functional verification (next release)

The background-automation version 1 recipe uses the existing Application, public API, private worker and PostgreSQL controllers. Submit uppercase, word_count or sha256 jobs through POST /jobs with a retained Idempotency-Key. Identical requests return the original job; the same key with different input returns 409. GET /jobs/:id returns its persisted status and result. The worker uses row locks, a 30-second lease, ownership-checked completion and at most five attempts. A crashed worker can leave an expired lease for another worker to recover. These deterministic tasks do not call external services or consume native AI credits. Add application authentication and per-user authorization before accepting sensitive production inputs. Every maintained sample now publishes verification.service_key, verification.script_path and verification.timeout_seconds. The build includes dist/test/smoke.sh. Select that script as a repository smoke criterion on the app/API workload after deployment. The runner supplies STACKSHIFT_SMOKE_BASE_URL. Local SAMPLE_URL remains supported. A user-supplied repository must provide its own reviewed script; the sample path is not a promise about arbitrary repositories. The PostgreSQL-only and background smoke checks write unique test data, verify the application result and, when DATABASE_URL is present, remove only their own data. The Assets/Mail check retains receipts and attachments for explicit cleanup. The background sample also verifies idempotent submissions and rejects a deliberately wrong result even when health succeeds. Downloaded archives include preview.json and the test sources. Background preview seeds are synthetic; production data is never copied. Upgrade through the retained recipe and a separately reviewed pinned release, preserving its database. Cleanup deletes created workloads before their owned database and never automatically deletes a reused database. Local PostgreSQL tests cover job submission, expired-lease recovery and functional rejection; they do not establish a new production deployment.

App + PostgreSQL + Assets + Mail, version 1

The app-postgres-assets-mail recipe uses the existing Application and PostgreSQL controllers, Node.js 22+ and the pinned StackShift SDK 1.3.1. The existing recipe supports supplied versioned references for ASSETS_API_KEY, ASSET_SPACE_ID, MAIL_API_KEY, MAIL_FROM, MAIL_TO and RECIPE_ACCESS_TOKEN (at least 32 random characters). Values never appear in setup responses. Assets and Mail storage, requests, delivery and usage retain their separate billing and are excluded from the infrastructure estimate. The authenticated POST /records endpoint accepts a message and UUID v4 Idempotency-Key. It saves the database record, uploads a private text attachment and records a Mail receipt. GET /records/:id reads the retained result. MAIL_MODE defaults to test and requests simulated delivery; real sending uses a live key and either StackShift’s default sender (no customer domain required) or a verified custom sender. The next-release smoke script accepts live Mail only with MAIL_MODE=live and STACKSHIFT_SMOKE_ALLOW_LIVE=true; it checks database write/read, downloads the private attachment through a one-use signed URL and verifies the matching Mail mode. Before writing, the check compares the target app’s mode and includes an X-Recipe-Mail-Mode precondition to reject a changed target mode. Output distinguishes submitted/provider-reported delivery from inbox confirmation, which still requires checking the recipient inbox. Test records remain for inspection. Repeated requests reuse the same database, asset and mail identities. A lost upload response is reconciled by exact asset key and record metadata. A lost mail response is reconciled from the latest 100 messages for its recipient and then checked against the full receipt. Unknown or ambiguous outcomes stop instead of resending. Keep the original request ID and inspect provider receipts. Another authorized client can continue through saved setup/release IDs and the application record receipt. Previews require fresh PostgreSQL, a dedicated test Asset Space and separate test references; live mail mode is refused in previews. Synthetic seeding writes fake records only. Preview cleanup does not delete external attachments automatically: delete exact owned assets with revision checks, wait for deletion jobs, then remove records. Preserve reused spaces, senders, databases and mail audit receipts. Upgrade through a separately reviewed source commit and Application release; the additive migration preserves data.

Guided Assets and Mail dependencies (next release)

The dashboard lists missing dependencies together. Select an accessible Asset Space or name a dedicated test space, choose simulated or live Mail, select the default sender or a custom sender, enter the recipient and choose generated credentials or existing encrypted references. The default sender needs no customer domain. Custom live sender setup saves the draft before opening Mail domains; use Return to saved recipe setup to continue. No Mail is sent during setup. After configuration review, the native app workload is created without deploying. The recipe.dependencies.configure step creates the selected test space and credentials inside the existing setup transaction, writes them to encrypted project variables and saves their IDs/versions. A failed write rolls back issuance; resuming the same saved receipt does not create duplicate credentials. Required bindings and PostgreSQL readiness gate the separately reviewed release. GET /api/v1/recipe-dependencies returns accessible Asset Spaces and the configured default sender, without credentials. The catalog dependencies array declares Assets, Mail and access-token variable groups. Optional configuration.dependencies contains asset_space_id OR new_asset_space_name, generate_assets_key, generate_mail_key, generate_access_token, mail_mode (test/live), mail_sender_mode (default/custom), optional mail_from and mail_to. With generation disabled, retain the corresponding versioned secret reference in services[].variables. Existing reference-only configurations remain compatible. Guided setup requires an owner session. Generated Assets keys have assets:read and assets:write restricted to the selected space; Mail keys have mail:send and mail:read in the selected mode. API keys expire after one year. The separate recipe access token is 256 random bits for the sample app. Existing references are checked server-side for ownership, secret storage, version, token validity, space, scopes, Mail mode and sender restrictions. Values are never returned in setup responses. Test Assets consume real storage. Simulation Mail creates receipts without inbox delivery. Live Mail retains native sender authorization, eligibility, limits and billing at send time. No extra server setting or migration is needed beyond existing secret encryption and Mail configuration. Cancellation retains created spaces, keys and app variables; revoke keys through Settings and clean up exact owned resources explicitly. Preview verification remains test-only even when the primary app uses live Mail.

Fresh WordPress staging and repair, version 1 (next release)

The governed wordpress.staging.create workflow reuses the native WordPress controller. It retains a distinct staging project and stack identity, pins the source runtime version, creates a fresh managed MySQL database and generates new administrator credentials. It copies placement only, not production content, credentials, domains, plugins or themes. Its result records recipe_version 1 and data_mode fresh_synthetic. This workflow uses native WordPress actions rather than the PostgreSQL Application recipe schema. Creation seeds a fixed synthetic page and checks its persisted identity and database. Cron is disabled, WordPress HTTP calls are blocked, and a must-use plugin suppresses WordPress mail. Readiness rechecks these guards and HTTP response. These application-level protections are not a network sandbox for arbitrary PHP. No production database or backup is read. The existing dashboard clone/import workflows are separate and retain their existing behavior. For repair, inspect an existing staging plugin/theme file, retain its SHA256, and propose wordpress.patch.staging with staging_action_id. The controller checks provenance, expected hash and PHP syntax before an atomic write. Inspect diagnostics and the HTTP result after the patch; a successful write alone is not a functional repair assertion. Fresh staging cannot reproduce production-only plugin/data failures without separately installing reviewed code and synthetic fixtures. Production patching remains a separate backup-gated approval. A supported client can resume using the retained creation action, target project and patch receipt. Retry uncertain creation against the original action identity; never create a replacement site to hide an unknown result. Updates use the existing native runtime/version and database-upgrade controls with separate approvals. Hosted staging reserves its own app, database and storage and retains their normal billing; owner-server workload hosting remains free within capacity. Cleanup explicitly removes the staging workload/stack before its owned database and volume; never delete the source site or reused resources. Live containerd deployment and WordPress runtime execution were not performed by this implementation pass.

Agent setup discovery and review recovery (next release)

Every catalog definition includes setup.template, setup.instructions and setup.discovery. The template is generated from that recipe’s roles, commands, ports, database version and required variable names. It is an unfinished request: replace repository/name selections, choose database.size_id, and fill required variable references before submitting. An existing repository needs its own inspected commands and roots; sample commands are not universal defaults. Use GET /api/v1/databases/size-options (stackshift api GET /api/v1/databases/size-options) to discover active PostgreSQL sizes and review their capacity and price. Use stackshift recipe variables for authorized variable IDs and expected versions. Keep secret values out of setup JSON. The catalog guide also explains sample publication, existing Application/database reuse and explicit connected-node placement. Placement reviews use an explicit projection of node identity, ownership, placement tags, agent version, security posture, runtime configuration, readiness and capabilities. Reporting clocks, historical incident summaries, allocation ledgers, free-capacity counters and diagnostic prose are not consent revisions. Live trust, heartbeat and capacity eligibility checks still run before execution. Meaningful placement changes require review; existing reviews created before this correction need a fresh plan once. A plan_stale response returns HTTP 409 with recovery instructions. If the review changes after admission but before any controller call, status returns to draft with the same pending step and plan_stale error_code; plan again without creating a retry attempt. Fetch the same setup, plan its remaining steps using its current expected_revision, review any changed resources or charges, then continue with a new request key. Do not create another setup or database. Replay an uncertain identical request with its original key; reconcile uncertain controller effects instead of retrying creation. Recipe-created workloads retain the account’s resource defaults. Inspect each workload’s memory, CPU, instance count and readiness policy before the separate release, and configure allocations appropriate for the application. The database size does not set workload resources. Release completion must be followed by HTTPS health and recipe-specific functional verification.

Saved setup API and receipts

After the retry repair is released, save-draft and update retain durable Idempotency-Key receipts. Retry the exact body, including expected_revision, with the same key after a lost acknowledgement. A committed retry returns the current setup without overwriting intervening edits; changed input with the old key is a conflict. A new edit requires the latest revision and a new key. The editor rotates its key only after acknowledgement. Owner APIs use /api/v1/recipe-setups. External connections use /api/v1/agents/connections/recipe-setups. POST saves recipe_id, recipe_version and non-secret configuration with a retained Idempotency-Key. GET lists setups; GET /{setupID} observes existing receipts without dispatching infrastructure. A setup saved for execution review still requires a complete configuration: source (kind, GitHub repository_url and branch), application (new/existing selection and explicit placement), database (existing ID or new name, size_id and version), and every recipe service role with explicit root and commands. Incomplete progress can be saved separately in onboarding state after the next release; it cannot be reviewed or executed until complete. Downloading a sample does not create a GitHub repository. Configuration validation errors identify the missing or invalid selection after the API validation-message update is deployed. Correct the request before retrying; an invalid_request response is not evidence that the CLI needs a different credential. Internal and authorization errors remain redacted. No infrastructure is created by a rejected draft. POST /{setupID}/plan accepts expected_revision and purpose configure or release. start, resume and release require retained idempotency keys; start/release use the matching review_hash. Update unfinished configuration through PUT /{setupID} or POST /{setupID}/update with expected_revision and configuration. Successful resource configuration cannot silently change. Editing unfinished configuration invalidates the remaining review. Unrelated target, node, variable-version or pricing changes require fresh review. Steps are serialized and persist intent before dispatch. Denied, cancelled and failed attempts do not become retries through Resume. After fresh review, retry-step requires step_id and confirm_new_attempt:true. Uncertain results require reconcile with the retained step_id, review_hash and confirm_reconcile:true; they reuse the original receipt rather than create a new resource attempt. Cancellation leaves resources intact. Resolve admitted operations through their existing approval/controller interface before cancelling or changing connections. Remote provisioning cannot be made atomic by the saved-setup database transaction.

Explicit external authority

A dashboard owner can POST /{setupID}/delegate with expected_revision and an explicitly selected connection_id. The selected connection must be active, belong to the same owner and already have the required scope. Assignment creates no grant, selects no policy and approves no action. Return from Settings alone makes no assignment. application.create remains hosted-only and single-bound. application.create.connected_node separately authorizes one Application on a persisted explicit target_node_id. Scope-preserving replacement cannot switch the node or broaden the placement. service.create continues to create public web workloads. service.create.worker is a separately named private-worker permission. service.variables.configure is separate consent for reference-based variable writes; both destination and source project/reference must be owner-accessible and inside the connection grant. Variable source versions are bound to reviewed execution and rechecked before writing. GET /recipe-variables exposes reference metadata only. An external connection cannot use a known variable ID to copy secrets outside its grant. Each external step uses ordinary connection admission, independent human or previously consented policy approval, and the existing native controller. A saved recipe is not privileged execution authority. Revocation and expiry still apply.

CLI and MCP continuation

The CLI recipe group calls the same connection recipe endpoints. Supply the normal supported connection credential. Use —file for non-secret request JSON and retain —idempotency-key with the exact request. A profile is not a resource grant. MCP exposes recipes, recipe_definition, recipe_setups, recipe_setup_create, recipe_setup_get, recipe_setup_action and recipe_variable_references. recipe_setup_action accepts the explicit action and reviewed request. The external caller cannot use owner delegation or approve its own proposals.

Cleanup and evidence boundaries

Delete created workloads before deleting a created database. Detach a reused database without deleting its data. Cleanup is a separate explicit governed operation; cancellation never performs blanket cleanup. The local native composition test covers resource creation, persistence, controlled database readiness and private writer binding without starting builds. Browser review uses an independent local API/database. Neither establishes hosting/BYOS deployment, production HTTPS, named-client interoperability or a live private endpoint. These changes are implemented locally and unreleased. No endpoint, sample repository, package or infrastructure has been published by this work.

Expected result

A persisted setup links native Application, workload, database and release records. Real deployment readiness and database write/read require their own runtime evidence.

Agent feature availability

Find the actions available to your agent and resolve access or configuration requirements.

Connect your coding agent

Connect an external client, choose its access and inspect its work in StackShift.

Connection access and approvals

Understand selected resources, permitted actions, owner decisions and revocation.

Agent connection API and OAuth

Separate owner governance from scoped execution, handle OAuth challenges and recover recorded operations.

Application and PostgreSQL with an external agent

Follow governed resource creation, private database binding and evidence-based deployment verification.