Docs

Stack inputs

Declare the values a deployment needs in alien.ts, mark who provides each one, and Alien validates and collects it across the dashboard, deployment portal, CLI, CloudFormation, Terraform, and Helm.

Most deployments need a few values that aren't known until setup: a database URL inside the customer's network, an API key for your control plane, a log level. Stack inputs let you declare those values in alien.ts, say who provides each one, and Alien handles collecting and validating them everywhere setup happens.

In BYOC, setup has two sides. Some values are yours, like a control-plane key. Some belong to the customer's admin, like an endpoint that only exists inside their network. If you hardcode values or pass ad hoc env flags, the deployment portal, generated IaC, and white-labeled CLI don't know those values exist, so an admin can follow setup and still end up with a broken deployment. Stack inputs fix that: one declaration drives every surface.

Declaring inputs

Declare a set with alien.inputs(...) and attach it to your stack with .inputs(). Each key is the input's id.

import * as alien from "@alienplatform/core"

const inputs = alien.inputs({
  databaseUrl: alien.string({
    providedBy: "deployer",
    required: true,
    label: "Database URL",
    description: "Postgres connection string inside the customer's network.",
    pattern: "^postgres://",
    env: "DATABASE_URL",
  }),
  controlPlaneApiKey: alien.secret({
    providedBy: "developer",
    required: true,
    label: "Control plane API key",
    description: "Authorizes this deployment with your control plane.",
    env: { name: "CONTROL_PLANE_API_KEY", targetResources: ["api"] },
  }),
  logLevel: alien.enum(["debug", "info", "warn", "error"], {
    providedBy: "deployer",
    required: false,
    label: "Log level",
    description: "Verbosity for the deployment's logs.",
    default: "info",
    env: "LOG_LEVEL",
  }),
})

export default new alien.Stack("acme-app").inputs(inputs).build()

Input ids are normal identifiers (letters, digits, underscores) and can't be all-caps env-var style. Every input needs a label, and a description is required whenever required is true.

Who provides a value

providedBy decides which side is asked for a value, and on which surfaces it appears.

providedByCollected onNotes
"developer"Your surfaces: alien onboard, the dashboard generate-link flow, deployment-group APIsNever shown to the customer and never emitted into generated IaC or the portal
"deployer"The customer's surfaces: deployment portal, generated CloudFormation, Terraform, Helm, and the white-labeled CLIAsked of the customer's admin at install time
["developer", "deployer"]BothYou can prefill it; if you don't, the admin is asked at install time

This is what keeps your secrets on your side: a developer input is collected only where you control it, so it never reaches the customer or lands in anything they can read.

Input types

alien.string({ ... })   // free text
alien.secret({ ... })   // masked, encrypted, no default
alien.number({ ... })   // any number
alien.integer({ ... })  // whole number
alien.boolean({ ... })  // true / false
alien.enum(["a", "b"], { ... })  // one of a fixed set
alien.stringList({ ... })        // list of strings

Every type takes the common options providedBy, required, label, description, and optionally placeholder, default (not for secret), platforms, and env. Use platforms to scope an input to specific targets, so a local-only value isn't requested for an AWS-only deployment link.

Validation

Validation is a small portable set, declared right on the input, so it's enforced identically in TypeScript, the deployment portal, CloudFormation, and Terraform.

TypeOptions
string, secretminLength, maxLength, pattern, format
number, integermin, max
enumthe allowed values
stringListminItems, maxItems

pattern is matched against the whole value. Keep it portable: no regex delimiters, backreferences, or lookarounds, since the same pattern has to run in CloudFormation rules and Terraform validation blocks, not just JavaScript.

webhookUrl: alien.string({
  providedBy: "deployer",
  required: true,
  label: "Webhook URL",
  description: "HTTPS endpoint the deployment calls back.",
  pattern: "^https://",
  maxLength: 2048,
  env: "WEBHOOK_URL",
}),

Environment variables

env maps an input into the deployment's runtime environment. Pass a variable name, or an object to target specific resources:

env: "DATABASE_URL"
env: { name: "DATABASE_URL", targetResources: ["api", "worker"] }

Variable names are upper snake case. By default an input is available to every resource; targetResources narrows it to the listed ones.

Secrets

alien.secret values are masked in the dashboard and portal, encrypted at rest, and kept out of generated IaC state, logs, and launch URLs. They can't declare a default, and they flow through Alien's runtime secret vault rather than plain environment snapshots.

What's next

On this page